| /* |
| * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package jdk.nashorn.internal.runtime.options; |
| |
| import java.util.Locale; |
| import java.util.TimeZone; |
| import jdk.nashorn.internal.runtime.QuotedStringTokenizer; |
| |
| /** |
| * This describes the valid input for an option, as read from the resource |
| * bundle file. Metainfo such as parameters and description is here as well |
| * for context sensitive help generation. |
| */ |
| public final class OptionTemplate implements Comparable<OptionTemplate> { |
| /** Resource, e.g. "nashorn" for this option */ |
| private final String resource; |
| |
| /** Key in the resource bundle */ |
| private final String key; |
| |
| /** Is this option a help option? */ |
| private final boolean isHelp; |
| |
| /** Is this option a extended help option? */ |
| private final boolean isXHelp; |
| |
| /** Name - for example --dump-on-error (usually prefixed with --) */ |
| private String name; |
| |
| /** Short name - for example -doe (usually prefixed with -) */ |
| private String shortName; |
| |
| /** Params - a parameter template string */ |
| private String params; |
| |
| /** Type - e.g. "boolean". */ |
| private String type; |
| |
| /** Does this option have a default value? */ |
| private String defaultValue; |
| |
| /** Does this option activate another option when set? */ |
| private String dependency; |
| |
| /** Does this option conflict with another? */ |
| private String conflict; |
| |
| /** Is this a documented option that should show up in help? */ |
| private boolean isUndocumented; |
| |
| /** A longer description of what this option does */ |
| private String description; |
| |
| /** is the option value specified as next argument? */ |
| private boolean valueNextArg; |
| |
| OptionTemplate(final String resource, final String key, final String value, final boolean isHelp, final boolean isXHelp) { |
| this.resource = resource; |
| this.key = key; |
| this.isHelp = isHelp; |
| this.isXHelp = isXHelp; |
| parse(value); |
| } |
| |
| /** |
| * Is this the special help option, used to generate help for |
| * all the others |
| * |
| * @return true if this is the help option |
| */ |
| public boolean isHelp() { |
| return this.isHelp; |
| } |
| |
| /** |
| * Is this the special extended help option, used to generate extended help for |
| * all the others |
| * |
| * @return true if this is the extended help option |
| */ |
| public boolean isXHelp() { |
| return this.isXHelp; |
| } |
| |
| /** |
| * Get the resource name used to prefix this option set, e.g. "nashorn" |
| * |
| * @return the name of the resource |
| */ |
| public String getResource() { |
| return this.resource; |
| } |
| |
| /** |
| * Get the type of this option |
| * |
| * @return the type of the option |
| */ |
| public String getType() { |
| return this.type; |
| } |
| |
| /** |
| * Get the key of this option |
| * |
| * @return the key |
| */ |
| public String getKey() { |
| return this.key; |
| } |
| |
| /** |
| * Get the default value for this option |
| * |
| * @return the default value as a string |
| */ |
| public String getDefaultValue() { |
| switch (getType()) { |
| case "boolean": |
| if (this.defaultValue == null) { |
| this.defaultValue = "false"; |
| } |
| break; |
| case "integer": |
| if (this.defaultValue == null) { |
| this.defaultValue = "0"; |
| } |
| break; |
| case "timezone": |
| this.defaultValue = TimeZone.getDefault().getID(); |
| break; |
| case "locale": |
| this.defaultValue = Locale.getDefault().toLanguageTag(); |
| break; |
| default: |
| break; |
| } |
| return this.defaultValue; |
| } |
| |
| /** |
| * Does this option automatically enable another option, i.e. a dependency. |
| * @return the dependency or null if none exists |
| */ |
| public String getDependency() { |
| return this.dependency; |
| } |
| |
| /** |
| * Is this option in conflict with another option so that both can't be enabled |
| * at the same time |
| * |
| * @return the conflicting option or null if none exists |
| */ |
| public String getConflict() { |
| return this.conflict; |
| } |
| |
| /** |
| * Is this option undocumented, i.e. should not show up in the standard help output |
| * |
| * @return true if option is undocumented |
| */ |
| public boolean isUndocumented() { |
| return this.isUndocumented; |
| } |
| |
| /** |
| * Get the short version of this option name if one exists, e.g. "-co" for "--compile-only" |
| * |
| * @return the short name |
| */ |
| public String getShortName() { |
| return this.shortName; |
| } |
| |
| /** |
| * Get the name of this option, e.g. "--compile-only". A name always exists |
| * |
| * @return the name of the option |
| */ |
| public String getName() { |
| return this.name; |
| } |
| |
| /** |
| * Get the description of this option. |
| * |
| * @return the description |
| */ |
| public String getDescription() { |
| return this.description; |
| } |
| |
| /** |
| * Is value of this option passed as next argument? |
| * @return boolean |
| */ |
| public boolean isValueNextArg() { |
| return valueNextArg; |
| } |
| |
| private static String strip(final String value, final char start, final char end) { |
| final int len = value.length(); |
| if (len > 1 && value.charAt(0) == start && value.charAt(len - 1) == end) { |
| return value.substring(1, len - 1); |
| } |
| return null; |
| } |
| |
| private void parse(final String origValue) { |
| String value = origValue.trim(); |
| |
| try { |
| value = OptionTemplate.strip(value, '{', '}'); |
| final QuotedStringTokenizer keyValuePairs = new QuotedStringTokenizer(value, ","); |
| |
| while (keyValuePairs.hasMoreTokens()) { |
| final String keyValue = keyValuePairs.nextToken(); |
| final QuotedStringTokenizer st = new QuotedStringTokenizer(keyValue, "="); |
| final String keyToken = st.nextToken(); |
| final String arg = st.nextToken(); |
| |
| switch (keyToken) { |
| case "is_undocumented": |
| this.isUndocumented = Boolean.parseBoolean(arg); |
| break; |
| case "name": |
| if (!arg.startsWith("-")) { |
| throw new IllegalArgumentException(arg); |
| } |
| this.name = arg; |
| break; |
| case "short_name": |
| if (!arg.startsWith("-")) { |
| throw new IllegalArgumentException(arg); |
| } |
| this.shortName = arg; |
| break; |
| case "desc": |
| this.description = arg; |
| break; |
| case "params": |
| this.params = arg; |
| break; |
| case "type": |
| this.type = arg.toLowerCase(Locale.ENGLISH); |
| break; |
| case "default": |
| this.defaultValue = arg; |
| break; |
| case "dependency": |
| this.dependency = arg; |
| break; |
| case "conflict": |
| this.conflict = arg; |
| break; |
| case "value_next_arg": |
| this.valueNextArg = Boolean.parseBoolean(arg); |
| break; |
| default: |
| throw new IllegalArgumentException(keyToken); |
| } |
| } |
| |
| // default to boolean if no type is given |
| if (this.type == null) { |
| this.type = "boolean"; |
| } |
| |
| if (this.params == null && "boolean".equals(this.type)) { |
| this.params = "[true|false]"; |
| } |
| |
| } catch (final Exception e) { |
| throw new IllegalArgumentException(origValue); |
| } |
| |
| if (name == null && shortName == null) { |
| throw new IllegalArgumentException(origValue); |
| } |
| } |
| |
| boolean nameMatches(final String aName) { |
| return aName.equals(this.shortName) || aName.equals(this.name); |
| } |
| |
| private static final int LINE_BREAK = 64; |
| |
| @Override |
| public String toString() { |
| final StringBuilder sb = new StringBuilder(); |
| |
| sb.append('\t'); |
| |
| if (shortName != null) { |
| sb.append(shortName); |
| if (name != null) { |
| sb.append(", "); |
| } |
| } |
| |
| if (name != null) { |
| sb.append(name); |
| } |
| |
| if (description != null) { |
| final int indent = sb.length(); |
| sb.append(' '); |
| sb.append('('); |
| int pos = 0; |
| for (final char c : description.toCharArray()) { |
| sb.append(c); |
| pos++; |
| if (pos >= LINE_BREAK && Character.isWhitespace(c)) { |
| pos = 0; |
| sb.append("\n\t"); |
| for (int i = 0; i < indent; i++) { |
| sb.append(' '); |
| } |
| } |
| } |
| sb.append(')'); |
| } |
| |
| if (params != null) { |
| sb.append('\n'); |
| sb.append('\t'); |
| sb.append('\t'); |
| sb.append(Options.getMsg("nashorn.options.param")).append(": "); |
| sb.append(params); |
| sb.append(" "); |
| final Object def = this.getDefaultValue(); |
| if (def != null) { |
| sb.append(Options.getMsg("nashorn.options.default")).append(": "); |
| sb.append(this.getDefaultValue()); |
| } |
| } |
| |
| |
| return sb.toString(); |
| } |
| |
| @Override |
| public int compareTo(final OptionTemplate o) { |
| return this.getKey().compareTo(o.getKey()); |
| } |
| } |