1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime.options; 27 28 import java.util.Locale; 29 import java.util.TimeZone; 30 import jdk.nashorn.internal.runtime.QuotedStringTokenizer; 31 32 /** 33 * This describes the valid input for an option, as read from the resource 34 * bundle file. Metainfo such as parameters and description is here as well 35 * for context sensitive help generation. 36 */ 37 public class OptionTemplate implements Comparable<OptionTemplate> { 38 /** Resource, e.g. "nashorn" for this option */ 39 private final String resource; 40 41 /** Key in the resource bundle */ 42 private final String key; 43 44 /** Is this option a help option? */ 45 private final boolean isHelp; 46 47 /** Is this option a extended help option? */ 48 private final boolean isXHelp; 49 50 /** Name - for example --dump-on-error (usually prefixed with --) */ 51 private String name; 52 53 /** Short name - for example -doe (usually prefixed with -) */ 54 private String shortName; 55 56 /** Params - a parameter template string */ 57 private String params; 58 59 /** Type - e.g. "boolean". */ 60 private String type; 61 62 /** Does this option have a default value? */ 63 private String defaultValue; 64 65 /** Does this option activate another option when set? */ 66 private String dependency; 67 68 /** Does this option conflict with another? */ 69 private String conflict; 70 71 /** Is this a documented option that should show up in help? */ 72 private boolean isUndocumented; 73 74 /** A longer description of what this option does */ 75 private String description; 76 77 /** is the option value specified as next argument? */ 78 private boolean valueNextArg; 79 80 OptionTemplate(final String resource, final String key, final String value, final boolean isHelp, final boolean isXHelp) { 81 this.resource = resource; 82 this.key = key; 83 this.isHelp = isHelp; 84 this.isXHelp = isXHelp; 85 parse(value); 86 } 87 88 /** 89 * Is this the special help option, used to generate help for 90 * all the others 91 * 92 * @return true if this is the help option 93 */ 94 public boolean isHelp() { 95 return this.isHelp; 96 } 97 98 /** 99 * Is this the special extended help option, used to generate extended help for 100 * all the others 101 * 102 * @return true if this is the extended help option 103 */ 104 public boolean isXHelp() { 105 return this.isXHelp; 106 } 107 108 /** 109 * Get the resource name used to prefix this option set, e.g. "nashorn" 110 * 111 * @return the name of the resource 112 */ 113 public String getResource() { 114 return this.resource; 115 } 116 117 /** 118 * Get the type of this option 119 * 120 * @return the type of the option 121 */ 122 public String getType() { 123 return this.type; 124 } 125 126 /** 127 * Get the key of this option 128 * 129 * @return the key 130 */ 131 public String getKey() { 132 return this.key; 133 } 134 135 /** 136 * Get the default value for this option 137 * 138 * @return the default value as a string 139 */ 140 public String getDefaultValue() { 141 switch (getType()) { 142 case "boolean": 143 if (this.defaultValue == null) { 144 this.defaultValue = "false"; 145 } 146 break; 147 case "integer": 148 if (this.defaultValue == null) { 149 this.defaultValue = "0"; 150 } 151 break; 152 case "timezone": 153 this.defaultValue = TimeZone.getDefault().getID(); 154 break; 155 default: 156 break; 157 } 158 return this.defaultValue; 159 } 160 161 /** 162 * Does this option automatically enable another option, i.e. a dependency. 163 * @return the dependecy or null if non exists 164 */ 165 public String getDependency() { 166 return this.dependency; 167 } 168 169 /** 170 * Is this option in conflict with another option so that both can't be enabled 171 * at the same time 172 * 173 * @return the conflicting option or null if none exists 174 */ 175 public String getConflict() { 176 return this.conflict; 177 } 178 179 /** 180 * Is this option undocumented, i.e. should not show up in the standard help output 181 * 182 * @return true if option is undocumented 183 */ 184 public boolean isUndocumented() { 185 return this.isUndocumented; 186 } 187 188 /** 189 * Get the short version of this option name if one exists, e.g. "-co" for "--compile-only" 190 * 191 * @return the short name 192 */ 193 public String getShortName() { 194 return this.shortName; 195 } 196 197 /** 198 * Get the name of this option, e.g. "--compile-only". A name always exists 199 * 200 * @return the name of the option 201 */ 202 public String getName() { 203 return this.name; 204 } 205 206 /** 207 * Get the description of this option. 208 * 209 * @return the description 210 */ 211 public String getDescription() { 212 return this.description; 213 } 214 215 /** 216 * Is value of this option passed as next argument? 217 * @return boolean 218 */ 219 public boolean isValueNextArg() { 220 return valueNextArg; 221 } 222 223 private static String strip(final String value, final char start, final char end) { 224 final int len = value.length(); 225 if (len > 1 && value.charAt(0) == start && value.charAt(len - 1) == end) { 226 return value.substring(1, len - 1); 227 } 228 return null; 229 } 230 231 private void parse(final String origValue) { 232 String value = origValue.trim(); 233 234 try { 235 value = OptionTemplate.strip(value, '{', '}'); 236 final QuotedStringTokenizer keyValuePairs = new QuotedStringTokenizer(value, ","); 237 238 while (keyValuePairs.hasMoreTokens()) { 239 final String keyValue = keyValuePairs.nextToken(); 240 final QuotedStringTokenizer st = new QuotedStringTokenizer(keyValue, "="); 241 final String keyToken = st.nextToken(); 242 final String arg = st.nextToken(); 243 244 switch (keyToken) { 245 case "is_undocumented": 246 this.isUndocumented = Boolean.parseBoolean(arg); 247 break; 248 case "name": 249 if (!arg.startsWith("-")) { 250 throw new IllegalArgumentException(arg); 251 } 252 this.name = arg; 253 break; 254 case "short_name": 255 if (!arg.startsWith("-")) { 256 throw new IllegalArgumentException(arg); 257 } 258 this.shortName = arg; 259 break; 260 case "desc": 261 this.description = arg; 262 break; 263 case "params": 264 this.params = arg; 265 break; 266 case "type": 267 this.type = arg.toLowerCase(Locale.ROOT); 268 break; 269 case "default": 270 this.defaultValue = arg; 271 break; 272 case "dependency": 273 this.dependency = arg; 274 break; 275 case "conflict": 276 this.conflict = arg; 277 break; 278 case "value_next_arg": 279 this.valueNextArg = Boolean.parseBoolean(arg); 280 break; 281 default: 282 throw new IllegalArgumentException(keyToken); 283 } 284 } 285 286 // default to boolean if no type is given 287 if (this.type == null) { 288 this.type = "boolean"; 289 } 290 291 if (this.params == null && "boolean".equals(this.type)) { 292 this.params = "[true|false]"; 293 } 294 295 } catch (final Exception e) { 296 throw new IllegalArgumentException(origValue); 297 } 298 299 if (name == null && shortName == null) { 300 throw new IllegalArgumentException(origValue); 301 } 302 } 303 304 boolean matches(final String key0) { 305 return key0.equals(this.shortName) || key0.equals(this.name); 306 } 307 308 private static final int LINE_BREAK = 64; 309 310 @Override 311 public String toString() { 312 final StringBuilder sb = new StringBuilder(); 313 314 sb.append('\t'); 315 316 if (shortName != null) { 317 sb.append(shortName); 318 if (name != null) { 319 sb.append(", "); 320 } 321 } 322 323 if (name != null) { 324 sb.append(name); 325 } 326 327 if (description != null) { 328 final int indent = sb.length(); 329 sb.append(' '); 330 sb.append('('); 331 int pos = 0; 332 for (final char c : description.toCharArray()) { 333 sb.append(c); 334 pos++; 335 if (pos >= LINE_BREAK && Character.isWhitespace(c)) { 336 pos = 0; 337 sb.append("\n\t"); 338 for (int i = 0; i < indent; i++) { 339 sb.append(' '); 340 } 341 } 342 } 343 sb.append(')'); 344 } 345 346 if (params != null) { 347 sb.append('\n'); 348 sb.append('\t'); 349 sb.append('\t'); 350 sb.append(Options.getMsg("nashorn.options.param")).append(": "); 351 sb.append(params); 352 sb.append(" "); 353 final Object def = this.getDefaultValue(); 354 if (def != null) { 355 sb.append(Options.getMsg("nashorn.options.default")).append(": "); 356 sb.append(this.getDefaultValue()); 357 } 358 } 359 360 361 return sb.toString(); 362 } 363 364 @Override 365 public int compareTo(final OptionTemplate o) { 366 return this.getKey().compareTo(o.getKey()); 367 } 368 } --- EOF ---