001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 020 package org.crsh.plugin; 021 022 import org.crsh.util.Utils; 023 024 import java.util.List; 025 import java.util.Arrays; 026 import java.util.Collections; 027 import java.util.HashMap; 028 import java.util.Map; 029 import java.util.concurrent.TimeUnit; 030 031 public abstract class PropertyDescriptor<T> { 032 033 /** The display value returned when a property is secret. */ 034 public static final String SECRET_DISPLAY_VALUE = "*****"; 035 036 public static PropertyDescriptor<String> create(String name, String defaultValue, String description, boolean secret) { 037 return new PropertyDescriptor<String>(String.class, name, defaultValue, description, secret) { 038 @Override 039 protected String doParse(String s) throws Exception { 040 return s; 041 } 042 }; 043 } 044 045 046 public static PropertyDescriptor<String> create(String name, String defaultValue, String description) { 047 return create(name, defaultValue, description, false); 048 } 049 050 public static PropertyDescriptor<Integer> create(String name, Integer defaultValue, String description, boolean secret) { 051 return new PropertyDescriptor<Integer>(Integer.class, name, defaultValue, description, secret) { 052 @Override 053 protected Integer doParse(String s) throws Exception { 054 return Integer.parseInt(s); 055 } 056 }; 057 } 058 059 public static PropertyDescriptor<Integer> create(String name, Integer defaultValue, String description) { 060 return create(name, defaultValue, description, false); 061 } 062 063 public static PropertyDescriptor<List> create(String name, List defaultValue, String description, boolean secret) { 064 return new PropertyDescriptor<List>(List.class, name, defaultValue, description, secret) { 065 @Override 066 protected List doParse(String s) throws Exception { 067 String[] split = Utils.split(s, ','); 068 List<String> list = Arrays.asList(split); 069 for (int i = 0;i < list.size();i++) { 070 list.set(i, list.get(i).trim()); 071 } 072 return list; 073 } 074 }; 075 } 076 077 public static PropertyDescriptor<List> create(String name, List defaultValue, String description) { 078 return create(name, defaultValue, description, false); 079 } 080 081 /** . */ 082 private static final Map<String, PropertyDescriptor<?>> INTERNAL_ALL = new HashMap<String, PropertyDescriptor<?>>(); 083 084 /** . */ 085 public static final Map<String, PropertyDescriptor<?>> ALL = Collections.unmodifiableMap(INTERNAL_ALL); 086 087 /** . */ 088 public static final PropertyDescriptor<TimeUnit> VFS_REFRESH_UNIT = new PropertyDescriptor<TimeUnit>(TimeUnit.class, "vfs.refresh_unit", TimeUnit.SECONDS, "The refresh time unit") { 089 @Override 090 public TimeUnit doParse(String s) { 091 return TimeUnit.valueOf(s); 092 } 093 }; 094 095 /** . */ 096 public static final PropertyDescriptor<Integer> VFS_REFRESH_PERIOD = PropertyDescriptor.create("vfs.refresh_period", (Integer)null, "The refresh rate period"); 097 098 /** . */ 099 public final Class<T> type; 100 101 /** . */ 102 public final String name; 103 104 /** . */ 105 public final T defaultValue; 106 107 /** . */ 108 public final String description; 109 110 /** . */ 111 public final boolean secret; 112 113 /** 114 * Create a new property descriptor. 115 * 116 * @param type the property type 117 * @param name the property name 118 * @param defaultValue the default value 119 * @param description the description 120 * @throws NullPointerException if the type, name or description is null 121 */ 122 protected PropertyDescriptor(Class<T> type, String name, T defaultValue, String description) throws NullPointerException { 123 this(type, name, defaultValue, description, false); 124 } 125 126 /** 127 * Create a new property descriptor. 128 * 129 * @param type the property type 130 * @param name the property name 131 * @param defaultValue the default value 132 * @param description the description 133 * @param secret the value is secret (like a password) 134 * @throws NullPointerException if the type, name or description is null 135 */ 136 protected PropertyDescriptor(Class<T> type, String name, T defaultValue, String description, boolean secret) throws NullPointerException { 137 if (type == null) { 138 throw new NullPointerException("No null type accepted"); 139 } 140 if (name == null) { 141 throw new NullPointerException("No null name accepted"); 142 } 143 if (description == null) { 144 throw new NullPointerException("No null description accepted"); 145 } 146 147 this.type = type; 148 this.name = name; 149 this.defaultValue = defaultValue; 150 this.description = description; 151 this.secret = secret; 152 153 // 154 INTERNAL_ALL.put(name, this); 155 } 156 157 public final String getName() { 158 return name; 159 } 160 161 public final String getDescription() { 162 return description; 163 } 164 165 public final Class<T> getType() { 166 return type; 167 } 168 169 public final T getDefaultValue() { 170 return defaultValue; 171 } 172 173 public final String getDefaultDisplayValue() { 174 return secret ? SECRET_DISPLAY_VALUE : String.valueOf(defaultValue); 175 } 176 177 /** 178 * Parse a string representation of a value and returns the corresponding typed value. 179 * 180 * @param s the string to parse 181 * @return the corresponding value 182 * @throws NullPointerException if the argument is null 183 * @throws IllegalArgumentException if the string value cannot be parsed for some reason 184 */ 185 public final T parse(String s) throws NullPointerException, IllegalArgumentException { 186 if (s == null) { 187 throw new NullPointerException("Cannot parse null property values"); 188 } 189 try { 190 return doParse(s); 191 } 192 catch (Exception e) { 193 throw new IllegalArgumentException("Illegal property value " + s, e); 194 } 195 } 196 197 @Override 198 public boolean equals(Object obj) { 199 if (obj == this) { 200 return true; 201 } else if (obj instanceof PropertyDescriptor<?>) { 202 PropertyDescriptor<?> that = (PropertyDescriptor<?>)obj; 203 return name.equals(that.name) && type.equals(that.type); 204 } else { 205 return false; 206 } 207 } 208 209 /** 210 * Parse a string representation of a value and returns the correspondig property value. 211 * 212 * @param s the string to parse 213 * @return the corresponding property 214 * @throws NullPointerException if the argument is null 215 * @throws IllegalArgumentException if the string value cannot be parsed for some reason 216 */ 217 public final Property<T> toProperty(String s) throws NullPointerException, IllegalArgumentException { 218 T value = parse(s); 219 return new Property<T>(this, value); 220 } 221 222 /** 223 * Implements the real parsing, the string argument must nto be null. The returned value must not be null instead an 224 * exception must be thrown. 225 * 226 * @param s the string to parse 227 * @return the related value 228 * @throws Exception any exception that would prevent parsing to hapen 229 */ 230 protected abstract T doParse(String s) throws Exception; 231 232 @Override 233 public final String toString() { 234 return "PropertyDescriptor[name=" + name + ",type=" + type.getName() + ",description=" + description + "]"; 235 } 236 }