001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package dwarfvsmodel;
043:
044: import com.sun.crypto.provider.DESCipher;
045: import java.io.PrintStream;
046: import java.util.*;
047:
048: /**
049: * Parses command line;
050: * stores options
051: * @author Vladimir Kvashin
052: */
053: public class Config {
054:
055: /** Exception that is thrown in the case of illegal argument(s) */
056: public static class WrongArgumentException extends Exception {
057: public WrongArgumentException(String message) {
058: super (message);
059: }
060: }
061:
062: /**
063: * Base class that represents a single option.
064: * Contains all functionality except for value type related.
065: */
066: public static abstract class Option {
067:
068: /** A key for identifying this option - setting via config file, system property, etc */
069: private String key;
070:
071: /** A brief, single-line, option description */
072: private String description;
073:
074: /** Possible command line switches */
075: private String[] switches;
076:
077: /**
078: * Command line switch that was used
079: * (this field is used mainly for error reporting)
080: */
081: private String usedSwitch;
082:
083: /**
084: * @param key A key for identifying this option - setting via config file, system property, etc
085: * @param description A brief, single-line, description of this option
086: * @param switches Possible command line switches
087: */
088: public Option(String key, String description,
089: String... switches) {
090: this .key = key;
091: this .description = description;
092: this .switches = switches;
093: usedSwitch = switches[0];
094: }
095:
096: /** Gets a key for identifying this option - setting via config file, system property, et */
097: public String getKey() {
098: return key;
099: }
100:
101: /** Gets a brief, single-line option description */
102: public String getDescription() {
103: return description;
104: }
105:
106: /** Determines whether the given switch corresponds to this option */
107: protected boolean accept(String sw) {
108: for (int i = 0; i < switches.length; i++) {
109: if (switches[i].equals(sw)) {
110: usedSwitch = sw;
111: used();
112: return true;
113: }
114: }
115: return false;
116: }
117:
118: /** Is called when this option has been set */
119: protected void used() {
120: }
121:
122: /** Determines whether this option needs value or not */
123: protected abstract boolean needsValue();
124:
125: /**
126: * Is called for each argument that follows this option's switch
127: * (i.e. the switch that is accepted by accept method)
128: *
129: */
130: protected abstract void parseValue(String value)
131: throws WrongArgumentException;
132:
133: /**
134: * Gets a command line switch that was used
135: * (this field is used mainly for error reporting)
136: */
137: protected String getUsedSwitch() {
138: return usedSwitch;
139: }
140:
141: /** Returns the value of this option converted to string */
142: protected abstract String getStringValue();
143: }
144:
145: /**
146: * Represents a single option of boolean type
147: */
148: public static class BooleanOption extends Option {
149:
150: private boolean value;
151:
152: public BooleanOption(String key, String description,
153: boolean defaultValue, String... switches) {
154: super (key, description, switches);
155: this .value = defaultValue;
156: }
157:
158: public boolean needsValue() {
159: return false;
160: }
161:
162: public void parseValue(String value)
163: throws WrongArgumentException {
164: throw new WrongArgumentException(getUsedSwitch()
165: + " option should bow be followed by a value"); //NOI18N
166: }
167:
168: public boolean getValue() {
169: return value;
170: }
171:
172: protected boolean accept(String sw) {
173: boolean reverse = sw.endsWith("-"); // NOI18N
174: if (reverse) {
175: sw = sw.substring(0, sw.length() - 1);
176: }
177: boolean accept = super .accept(sw);
178: if (accept) {
179: value = !reverse;
180: }
181: return accept;
182: }
183:
184: protected String getStringValue() {
185: return value ? "yes" : "no"; // NOI18N
186: }
187: }
188:
189: public static class StringOption extends Option {
190:
191: private String value;
192:
193: public StringOption(String key, String description,
194: String defaultValue, String... switches) {
195: super (key, description, switches);
196: this .value = defaultValue;
197: }
198:
199: public boolean needsValue() {
200: return true;
201: }
202:
203: public void parseValue(String value)
204: throws WrongArgumentException {
205: this .value = value;
206: }
207:
208: public String getValue() {
209: return value;
210: }
211:
212: protected String getStringValue() {
213: return value;
214: }
215:
216: }
217:
218: public static class StringListOption extends Option {
219:
220: private List<String> values = new ArrayList<String>();
221:
222: public StringListOption(String key, String description,
223: String... switches) {
224: super (key, description, switches);
225: }
226:
227: public boolean needsValue() {
228: return true;
229: }
230:
231: public void parseValue(String value)
232: throws WrongArgumentException {
233: this .values.add(value);
234: }
235:
236: public List<String> getValue() {
237: return values;
238: }
239:
240: protected String getStringValue() {
241: return values.toString();
242: }
243:
244: }
245:
246: /** Maps option keys to options */
247: private Map<String, Option> map = new HashMap<String, Option>();
248:
249: /** Holds a list of options in order they were added */
250: private List<Option> list = new ArrayList<Option>();
251:
252: private List<String> parameters = new ArrayList<String>();
253:
254: public BooleanOption addBooleanOption(String key,
255: String description, boolean defaultValue,
256: String... switches) {
257: BooleanOption option = new BooleanOption(key, description,
258: defaultValue, switches);
259: addOption(option);
260: return option;
261: }
262:
263: public StringOption addStringOption(String key, String description,
264: String defaultValue, String... switches) {
265: StringOption option = new StringOption(key, description,
266: defaultValue, switches);
267: addOption(option);
268: return option;
269: }
270:
271: public StringListOption addStringListOption(String key,
272: String description, String... switches) {
273: StringListOption option = new StringListOption(key,
274: description, switches);
275: addOption(option);
276: return option;
277: }
278:
279: /** Gets a list of options in order they were added */
280: public List<Option> getOptions() {
281: return list;
282: }
283:
284: public List<String> getParameters() {
285: return parameters;
286: }
287:
288: private void addOption(Option option) {
289: for (Option curr : map.values()) {
290: for (int i = 0; i < curr.switches.length; i++) {
291: for (int j = 0; j < option.switches.length; j++) {
292: if (option.switches[j].equals(curr.switches[i])) {
293: throw new IllegalArgumentException(
294: "Duplicate option switches: "
295: + // NOI18N
296: option.switches[j] + " and "
297: + curr.switches[i]); //NOI18N
298: }
299: }
300: }
301: }
302: map.put(option.getKey(), option);
303: list.add(option);
304: }
305:
306: private Option findOption(String sw) throws WrongArgumentException {
307: for (Option option : map.values()) {
308: if (option.accept(sw)) {
309: return option;
310: }
311: }
312: throw new WrongArgumentException("Unsupported option -" + sw); //NOI18N
313: }
314:
315: private Iterator<String> convert(final String[] args) {
316: return new Iterator<String>() {
317: private int cursor = 0;
318:
319: public boolean hasNext() {
320: return cursor < args.length;
321: }
322:
323: public void remove() {
324: throw new UnsupportedOperationException();
325: }
326:
327: public String next() {
328: return args[cursor++];
329: }
330:
331: };
332: }
333:
334: private void parse(Option option, Iterator<String> it)
335: throws WrongArgumentException {
336: if (option.needsValue()) {
337: if (it.hasNext()) {
338: String value = it.next();
339: if (value.startsWith("-")) { // NOI18N
340: throwRequiresValue(option);
341: } else {
342: option.parseValue(value);
343: }
344: } else {
345: throwRequiresValue(option);
346: }
347: }
348: }
349:
350: private void throwRequiresValue(Option option)
351: throws WrongArgumentException {
352: throw new WrongArgumentException("Option -"
353: + option.getUsedSwitch() + " requires a value"); //NOI18N
354: }
355:
356: public void parse(String[] args) throws WrongArgumentException {
357:
358: Iterator<String> it = convert(args);
359: while (it.hasNext()) {
360: String arg = it.next();
361: if (arg.startsWith("--")) { // NOI18N
362: parse(findOption(arg.substring(2)), it);
363: } else if (arg.startsWith("-")) { // NOI18N
364: Option option = findOption(arg.substring(1, 2));
365: if (arg.length() == 2) {
366: // just one flag
367: parse(option, it);
368: } else {
369: // several flags or value?
370: if (option.needsValue()) {
371: option.parseValue(arg.substring(2));
372: } else {
373: for (int pos = 2; pos < arg.length(); pos++) {
374: Option nextOption = findOption(arg
375: .substring(pos, pos + 1));
376: if (nextOption.needsValue()) {
377: throwRequiresValue(option);
378: }
379: }
380: }
381: }
382: } else {
383: parameters.add(arg);
384: }
385: }
386: }
387:
388: public void readProperties(Properties props)
389: throws WrongArgumentException {
390: for (Map.Entry entry : props.entrySet()) {
391: Option option = map.get(entry.getKey());
392: if (option != null) {
393: option.used();
394: if (option.needsValue()) {
395: option.parseValue((String) entry.getValue());
396: }
397: }
398: }
399: }
400:
401: public Option getOption(String key) {
402: Option option = map.get(key);
403: if (option == null) {
404: throw new IllegalArgumentException("No such option: " + key); //NOI18N
405: }
406: return option;
407: }
408:
409: public String getStringValue(String key) {
410: return getOption(key).getStringValue();
411: }
412:
413: public void dump(PrintStream ps) {
414: for (Option option : getOptions()) {
415: ps.println(option.getDescription() + ": \t"
416: + option.getStringValue()); // NOI18N
417: }
418: ps.println("Parameters:"); // NOI18N
419: for (String parameter : parameters) {
420: ps.println(parameter);
421: }
422: }
423: }
|