Révision 890
tmp/org.txm.libs.args4j/.project (revision 890) | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<projectDescription> |
|
3 |
<name>org.txm.libs.args4j</name> |
|
4 |
<comment></comment> |
|
5 |
<projects> |
|
6 |
</projects> |
|
7 |
<buildSpec> |
|
8 |
<buildCommand> |
|
9 |
<name>org.eclipse.jdt.core.javabuilder</name> |
|
10 |
<arguments> |
|
11 |
</arguments> |
|
12 |
</buildCommand> |
|
13 |
<buildCommand> |
|
14 |
<name>org.eclipse.pde.ManifestBuilder</name> |
|
15 |
<arguments> |
|
16 |
</arguments> |
|
17 |
</buildCommand> |
|
18 |
<buildCommand> |
|
19 |
<name>org.eclipse.pde.SchemaBuilder</name> |
|
20 |
<arguments> |
|
21 |
</arguments> |
|
22 |
</buildCommand> |
|
23 |
</buildSpec> |
|
24 |
<natures> |
|
25 |
<nature>org.eclipse.pde.PluginNature</nature> |
|
26 |
<nature>org.eclipse.jdt.core.javanature</nature> |
|
27 |
</natures> |
|
28 |
</projectDescription> |
|
0 | 29 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/XmlParser.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import java.lang.reflect.AccessibleObject; |
|
4 |
import java.net.URL; |
|
5 |
|
|
6 |
import org.kohsuke.args4j.spi.ArgumentImpl; |
|
7 |
import org.kohsuke.args4j.spi.ConfigElement; |
|
8 |
import org.kohsuke.args4j.spi.OptionImpl; |
|
9 |
import org.kohsuke.args4j.spi.Setters; |
|
10 |
import org.xml.sax.InputSource; |
|
11 |
|
|
12 |
/** |
|
13 |
* Parses an XML-file specifying the 'annotations'. |
|
14 |
* The XML must have the structure: |
|
15 |
* <pre> |
|
16 |
* <args> |
|
17 |
* <option field="" method="" name="" usage="" metavar="" handler=""/> |
|
18 |
* <argument field="" method="" usage="" metavar="" handler=""/> |
|
19 |
* </args> |
|
20 |
* </pre> |
|
21 |
* Exactly one of the attributes 'field' or 'method' must be set. |
|
22 |
* The 'handler' value specifies a full qualified class name. |
|
23 |
* |
|
24 |
* <h3>Example</h3> |
|
25 |
* <pre> |
|
26 |
* <args> |
|
27 |
* <option field="recursive" name="-r" usage="recursively run something"/> |
|
28 |
* <option field="out" name="-o" usage="output to this file" metavar="OUTPUT"/> |
|
29 |
* <option method="setStr(String)" name="-str"/> |
|
30 |
* <option field="data" name="-custom" handler="org.kohsuke.args4j.spi.BooleanOptionHandler" usage="boolean value for checking the custom handler"/> |
|
31 |
* <argument field="arguments"/> |
|
32 |
* <args> |
|
33 |
* </pre> |
|
34 |
* |
|
35 |
* @author Jan Materne |
|
36 |
*/ |
|
37 |
public class XmlParser { |
|
38 |
public void parse(URL xml, CmdLineParser parser, Object bean) { |
|
39 |
parse(new InputSource(xml.toExternalForm()),parser,bean); |
|
40 |
} |
|
41 |
|
|
42 |
public void parse(InputSource xml, CmdLineParser parser, Object bean) { |
|
43 |
try { |
|
44 |
Config config = Config.parse(xml); |
|
45 |
for(ConfigElement ce : config.options) { |
|
46 |
Option option = new OptionImpl(ce); |
|
47 |
parser.addOption(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), option); |
|
48 |
} |
|
49 |
for (ConfigElement ce : config.arguments) { |
|
50 |
Argument argument = new ArgumentImpl(ce); |
|
51 |
parser.addArgument(Setters.create(parser, findMethodOrField(bean, ce.field, ce.method),bean), argument); |
|
52 |
} |
|
53 |
} catch (Exception e) { |
|
54 |
throw new RuntimeException(Messages.METADATA_ERROR.format(), e); |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
58 |
|
|
59 |
/** |
|
60 |
* Finds a {@link java.lang.reflect.Method} or {@link java.lang.reflect.Method} in the bean |
|
61 |
* instance with the requested name. |
|
62 |
* @param bean bean instance |
|
63 |
* @param field name of the field (field XOR method must be specified) |
|
64 |
* @param method name of the method (field XOR method must be specified) |
|
65 |
* @return the reflection reference |
|
66 |
* @throws SecurityException |
|
67 |
* @throws NoSuchFieldException |
|
68 |
* @throws NoSuchMethodException |
|
69 |
* @throws ClassNotFoundException |
|
70 |
*/ |
|
71 |
private AccessibleObject findMethodOrField(Object bean, String field, String method) throws SecurityException, NoSuchFieldException, NoSuchMethodException, ClassNotFoundException { |
|
72 |
AccessibleObject rv; |
|
73 |
if (field != null) { |
|
74 |
rv = bean.getClass().getDeclaredField(field); |
|
75 |
} else { |
|
76 |
String methodName = method.substring(0, method.indexOf("(")); |
|
77 |
String[] params = method.substring(method.indexOf("(")+1, method.indexOf(")")).split(","); |
|
78 |
Class[] paramTypes = new Class[params.length]; |
|
79 |
for(int i=0; i<params.length; i++) { |
|
80 |
String className = params[i]; |
|
81 |
if (className.indexOf('.') < 0) { |
|
82 |
className = "java.lang." + className; |
|
83 |
} |
|
84 |
paramTypes[i] = Class.forName(className); |
|
85 |
} |
|
86 |
rv = bean.getClass().getMethod(methodName, paramTypes); |
|
87 |
} |
|
88 |
return rv; |
|
89 |
} |
|
90 |
|
|
91 |
} |
|
0 | 92 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/IllegalAnnotationError.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
/** |
|
4 |
* Signals an incorrect use of args4j annotations. |
|
5 |
* |
|
6 |
* <p> |
|
7 |
* This only happens when there's something wrong with the way you use |
|
8 |
* args4j in your code, not when the arguments supplied by the user is |
|
9 |
* wrong. Hence this class is an {@link Error}. |
|
10 |
* |
|
11 |
* @author Kohsuke Kawaguchi |
|
12 |
*/ |
|
13 |
public class IllegalAnnotationError extends Error { |
|
14 |
private static final long serialVersionUID = 2397757838147693218L; |
|
15 |
|
|
16 |
public IllegalAnnotationError(String message) { |
|
17 |
super(message); |
|
18 |
} |
|
19 |
|
|
20 |
public IllegalAnnotationError(String message, Throwable cause) { |
|
21 |
super(message, cause); |
|
22 |
} |
|
23 |
|
|
24 |
public IllegalAnnotationError(Throwable cause) { |
|
25 |
super(cause); |
|
26 |
} |
|
27 |
} |
|
0 | 28 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/package.html (revision 890) | ||
---|---|---|
1 |
<html><body> |
|
2 |
<p>Core classes of the Args4J command line parser.</p> |
|
3 |
|
|
4 |
<h1>What is Args4J</h1> |
|
5 |
<p>Args4J is a command line parser. As such a parser its job is to parse the String-array passed to the main() method |
|
6 |
and transfer the values to a java object, which includes type conversion. The entry point into this parsing is |
|
7 |
the CmdLineParser class with its parse() Method.</p> |
|
8 |
<p>Args4J must know the mapping between the flag from the command line and the target for the value. |
|
9 |
There are multiple ways for Args4J: <ul> |
|
10 |
<li>place an @Option or @Argument annotation at a setter or on a field</li> |
|
11 |
<li>provide a XML configuration file</li> |
|
12 |
<li>make all fields public available</li> |
|
13 |
</ul> |
|
14 |
depending on what you want, you have to do a configuration step before starting the parsing.</p> |
|
15 |
|
|
16 |
<h1>Examples</h1> |
|
17 |
|
|
18 |
<p><tt>java Main -text newText</tt></p> |
|
19 |
|
|
20 |
<p>The standard use case is having a bean class and providing the annotations. |
|
21 |
This feature is available since the first Args4J release: |
|
22 |
<!-- TODO: |
|
23 |
Javadoc stops when reaching the at-sign. When I load the package.html directly into Firefox, |
|
24 |
all is fine. But when creating the javadoc it stops copying the content at that sign. |
|
25 |
(a) is a compromise here ... |
|
26 |
Does anyone know how to handle that? |
|
27 |
--> |
|
28 |
<pre> |
|
29 |
public class Bean { |
|
30 |
(a)Option(name="-text") |
|
31 |
String text; |
|
32 |
} |
|
33 |
public class Main { |
|
34 |
public static void main(String[] args) throws CmdLineException { |
|
35 |
Object bean = new Bean(); |
|
36 |
CmdLineParser parser = new CmdLineParser(bean); |
|
37 |
parser.parse(args); |
|
38 |
} |
|
39 |
} |
|
40 |
</pre> |
|
41 |
|
|
42 |
<p>An easy way for initializing fields and not touching the bean source code |
|
43 |
is using the FieldParser. The FieldParser scans all fields of the bean class |
|
44 |
(including inheritance) and makes them public available as options with |
|
45 |
a '-' prefix in the name. |
|
46 |
This feature is available since Args4J release 2.0.16: |
|
47 |
<pre> |
|
48 |
public class Bean { |
|
49 |
String text; |
|
50 |
} |
|
51 |
public class Main { |
|
52 |
public static void main(String[] args) throws CmdLineException { |
|
53 |
Object bean = new Bean(); |
|
54 |
CmdLineParser parser = new CmdLineParser(null); |
|
55 |
new FieldParser().parse(parser, bean); |
|
56 |
parser.parse(args); |
|
57 |
} |
|
58 |
} |
|
59 |
</pre> |
|
60 |
|
|
61 |
<p>While the FieldParser is easier to use, the XmlParser supports more features. |
|
62 |
That said it supports all features which are available via annotations: usage text, specifying handlers and more. |
|
63 |
You have to provide an XML InputSource or an URL to the XML file. |
|
64 |
This feature is available since Args4J release 2.0.16: |
|
65 |
<pre> |
|
66 |
public class Bean { |
|
67 |
String text; |
|
68 |
} |
|
69 |
public class Main { |
|
70 |
public static void main(String[] args) throws CmdLineException { |
|
71 |
Object bean = new Bean(); |
|
72 |
CmdLineParser parser = new CmdLineParser(null); |
|
73 |
new XmlParser().parse(getClass().getResource(bean.getClass().getName() + ".xml"), parser, bean); |
|
74 |
parser.parse(args); |
|
75 |
} |
|
76 |
} |
|
77 |
<args> |
|
78 |
<option field="text" name="-text" usage="Output text"/> |
|
79 |
</args> |
|
80 |
</pre> |
|
81 |
</p> |
|
82 |
|
|
83 |
|
|
84 |
</body></html> |
|
0 | 85 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/Argument.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import java.lang.annotation.Retention; |
|
4 |
import java.lang.annotation.Target; |
|
5 |
|
|
6 |
import org.kohsuke.args4j.spi.OptionHandler; |
|
7 |
|
|
8 |
import static java.lang.annotation.RetentionPolicy.RUNTIME; |
|
9 |
import static java.lang.annotation.ElementType.FIELD; |
|
10 |
import static java.lang.annotation.ElementType.METHOD; |
|
11 |
import static java.lang.annotation.ElementType.PARAMETER; |
|
12 |
|
|
13 |
/** |
|
14 |
* Argument of the command line. |
|
15 |
* |
|
16 |
* This works mostly like {@link Option} except the following differences. |
|
17 |
* |
|
18 |
* <ol> |
|
19 |
* <li>Arguments have an index about their relative position on the command line. |
|
20 |
* </ol> |
|
21 |
* |
|
22 |
* @author Kohsuke Kawaguchi |
|
23 |
* @author Mark Sinke |
|
24 |
*/ |
|
25 |
@Retention(RUNTIME) |
|
26 |
@Target({FIELD,METHOD,PARAMETER}) |
|
27 |
public @interface Argument { |
|
28 |
/** |
|
29 |
* See {@link Option#usage()}. |
|
30 |
*/ |
|
31 |
String usage() default ""; //$NON-NLS-1$ |
|
32 |
/** |
|
33 |
* See {@link Option#metaVar()}. |
|
34 |
*/ |
|
35 |
String metaVar() default ""; //$NON-NLS-1$ |
|
36 |
/** |
|
37 |
* See {@link Option#required()}. |
|
38 |
*/ |
|
39 |
boolean required() default false; |
|
40 |
|
|
41 |
/** |
|
42 |
* See {@link Option#handler()}. |
|
43 |
*/ |
|
44 |
Class<? extends OptionHandler> handler() default OptionHandler.class; |
|
45 |
|
|
46 |
/** |
|
47 |
* Position of the argument. |
|
48 |
* |
|
49 |
* <p> |
|
50 |
* If you define multiple single value properties to bind to arguments, |
|
51 |
* they should have index=0, index=1, index=2, ... and so on. |
|
52 |
* |
|
53 |
* <p> |
|
54 |
* Multi value properties bound to arguments must be always the last entry. |
|
55 |
*/ |
|
56 |
int index() default 0; |
|
57 |
|
|
58 |
/** |
|
59 |
* See {@link Option#multiValued()}. |
|
60 |
*/ |
|
61 |
boolean multiValued() default false; |
|
62 |
} |
|
0 | 63 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/ClassParser.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import org.kohsuke.args4j.spi.MethodSetter; |
|
4 |
import org.kohsuke.args4j.spi.Setters; |
|
5 |
|
|
6 |
import java.lang.reflect.Field; |
|
7 |
import java.lang.reflect.Method; |
|
8 |
|
|
9 |
/** |
|
10 |
* Parser for analyzing Args4J annotations in the class hierarchy. |
|
11 |
* |
|
12 |
* This can be used to feed option bindings that span across multiple instances. |
|
13 |
* |
|
14 |
* @author Jan Materne |
|
15 |
*/ |
|
16 |
public class ClassParser { |
|
17 |
public void parse(Object bean, CmdLineParser parser) { |
|
18 |
// recursively process all the methods/fields. |
|
19 |
for( Class c=bean.getClass(); c!=null; c=c.getSuperclass()) { |
|
20 |
for( Method m : c.getDeclaredMethods() ) { |
|
21 |
Option o = m.getAnnotation(Option.class); |
|
22 |
if(o!=null) { |
|
23 |
parser.addOption(new MethodSetter(parser,bean,m), o); |
|
24 |
} |
|
25 |
Argument a = m.getAnnotation(Argument.class); |
|
26 |
if(a!=null) { |
|
27 |
parser.addArgument(new MethodSetter(parser,bean,m), a); |
|
28 |
} |
|
29 |
} |
|
30 |
|
|
31 |
for( Field f : c.getDeclaredFields() ) { |
|
32 |
Option o = f.getAnnotation(Option.class); |
|
33 |
if(o!=null) { |
|
34 |
parser.addOption(Setters.create(f,bean),o); |
|
35 |
} |
|
36 |
Argument a = f.getAnnotation(Argument.class); |
|
37 |
if(a!=null) { |
|
38 |
parser.addArgument(Setters.create(f,bean), a); |
|
39 |
} |
|
40 |
} |
|
41 |
} |
|
42 |
} |
|
43 |
} |
|
0 | 44 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/Messages.properties (revision 890) | ||
---|---|---|
1 |
MISSING_OPERAND = \ |
|
2 |
Option "{0}" takes an operand |
|
3 |
|
|
4 |
UNDEFINED_OPTION = \ |
|
5 |
"{0}" is not a valid option |
|
6 |
|
|
7 |
NO_ARGUMENT_ALLOWED = \ |
|
8 |
No argument is allowed: {0} |
|
9 |
|
|
10 |
REQUIRED_OPTION_MISSING = \ |
|
11 |
Option "{0}" is required |
|
12 |
|
|
13 |
REQUIRED_ARGUMENT_MISSING = \ |
|
14 |
Argument "{0}" is required |
|
15 |
|
|
16 |
TOO_MANY_ARGUMENTS = \ |
|
17 |
Too many arguments: {0} |
|
18 |
|
|
19 |
METADATA_ERROR = \ |
|
20 |
Problems while reading the args-confguration. |
|
21 |
|
|
22 |
MULTIPLE_USE_OF_ARGUMENT = \ |
|
23 |
Argument with index {0} is used more than once |
|
24 |
|
|
25 |
MULTIPLE_USE_OF_OPTION = \ |
|
26 |
Option name {0} is used more than once |
|
27 |
|
|
28 |
UNKNOWN_HANDLER = \ |
|
29 |
No OptionHandler is registered to handle {0} |
|
30 |
|
|
31 |
NO_OPTIONHANDLER = \ |
|
32 |
Not an OptionHandler class |
|
33 |
|
|
34 |
NO_CONSTRUCTOR_ON_HANDLER = \ |
|
35 |
{0} does not have the proper constructor |
|
36 |
|
|
37 |
FORMAT_ERROR_FOR_MAP = \ |
|
38 |
An argument for setting a Map must contain a "=" |
|
39 |
|
|
40 |
UNDEFINNED_WIDGET = \ |
|
41 |
Undefined widget {0}. Choose between {1} |
|
42 |
|
|
43 |
MAP_HAS_NO_KEY = \ |
|
44 |
A key must be set. |
|
0 | 45 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/Starter.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import java.lang.annotation.Annotation; |
|
4 |
import java.lang.reflect.Field; |
|
5 |
import java.lang.reflect.InvocationTargetException; |
|
6 |
import java.lang.reflect.Method; |
|
7 |
|
|
8 |
/** |
|
9 |
* Starter class which uses reflection to instantiate the business |
|
10 |
* class, parse the command line parameters, sets the fields of the |
|
11 |
* business class and doing the help message handling. |
|
12 |
* |
|
13 |
* @author Jan Materne |
|
14 |
*/ |
|
15 |
public class Starter { |
|
16 |
|
|
17 |
/** |
|
18 |
* The name of the JavaVM property which stores the class name of |
|
19 |
* the business class. |
|
20 |
* {@value} |
|
21 |
*/ |
|
22 |
public static final String PARAMETER_NAME = "mainclass"; |
|
23 |
|
|
24 |
public static void main(String[] args) { |
|
25 |
String classname = System.getProperty(PARAMETER_NAME); |
|
26 |
CmdLineParser parser = null; |
|
27 |
boolean classHasArgument = false; |
|
28 |
boolean classHasOptions = false; |
|
29 |
|
|
30 |
// Check the requirement: must specify the class to start |
|
31 |
if (classname == null || "".equals(classname)) { |
|
32 |
System.err.println("The system property '" |
|
33 |
+ PARAMETER_NAME |
|
34 |
+ "' must contain the classname to start."); |
|
35 |
} |
|
36 |
|
|
37 |
try { |
|
38 |
Class clazz = Class.forName(classname); |
|
39 |
Object bean = clazz.newInstance(); |
|
40 |
parser = new CmdLineParser(bean); |
|
41 |
|
|
42 |
// for help output |
|
43 |
classHasArgument = hasAnnotation(clazz, Argument.class); |
|
44 |
classHasOptions = hasAnnotation(clazz, Option.class); |
|
45 |
|
|
46 |
parser.parseArgument(args); |
|
47 |
|
|
48 |
// try starting run() |
|
49 |
Method m; |
|
50 |
boolean couldInvoke = false; |
|
51 |
try { |
|
52 |
m = clazz.getMethod("run", (Class[]) null); |
|
53 |
m.invoke(bean, (Object[]) null); |
|
54 |
couldInvoke = true; |
|
55 |
} catch (SecurityException e) { |
|
56 |
} catch (IllegalArgumentException e) { |
|
57 |
} catch (NoSuchMethodException e) { |
|
58 |
} catch (IllegalAccessException e) { |
|
59 |
} catch (InvocationTargetException e) { |
|
60 |
} |
|
61 |
|
|
62 |
// try starting run(String[]) |
|
63 |
if (!couldInvoke) try { |
|
64 |
m = clazz.getMethod("run", String[].class); |
|
65 |
m.invoke(bean, new Object[]{args}); |
|
66 |
couldInvoke = true; |
|
67 |
} catch (SecurityException e) { |
|
68 |
} catch (IllegalArgumentException e) { |
|
69 |
e.printStackTrace(); |
|
70 |
} catch (NoSuchMethodException e) { |
|
71 |
} catch (IllegalAccessException e) { |
|
72 |
} catch (InvocationTargetException e) { |
|
73 |
} |
|
74 |
} catch (ClassNotFoundException e) { |
|
75 |
// wrong classpath setting |
|
76 |
System.err.println("Cant find the class '" |
|
77 |
+ classname |
|
78 |
+ "' as specified in the system property '" |
|
79 |
+ PARAMETER_NAME + "'."); |
|
80 |
} catch (CmdLineException e) { |
|
81 |
// wrong argument enteres, so print the usage message as |
|
82 |
// supplied by args4j |
|
83 |
System.err.println(e.getMessage()); |
|
84 |
System.err.print(classname); |
|
85 |
if (classHasOptions) System.err.print(" [options]"); |
|
86 |
if (classHasArgument) System.err.print(" arguments"); |
|
87 |
System.err.println(); |
|
88 |
if (parser != null) |
|
89 |
parser.printUsage(System.err); |
|
90 |
} catch (Exception e) { |
|
91 |
// Must be an unhandled business exception, so we can only |
|
92 |
// print stacktraces. |
|
93 |
e.printStackTrace(); |
|
94 |
} |
|
95 |
} |
|
96 |
|
|
97 |
public static boolean hasAnnotation(Class clazz, Class<? extends Annotation> annotation) { |
|
98 |
if (clazz.getAnnotation(annotation)!=null) return true; |
|
99 |
for (Field f : clazz.getFields()) { |
|
100 |
if (f.getAnnotation(annotation)!=null) return true; |
|
101 |
} |
|
102 |
for (Method m : clazz.getMethods()) { |
|
103 |
if (m.getAnnotation(annotation)!=null) return true; |
|
104 |
} |
|
105 |
return false; |
|
106 |
} |
|
107 |
|
|
108 |
} |
|
0 | 109 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/OptionDef.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import org.kohsuke.args4j.spi.OptionHandler; |
|
4 |
|
|
5 |
/** |
|
6 |
* Run-time copy of the Option or Argument annotation. By definition, unnamed options |
|
7 |
* are arguments (and instances of this class). Named options are actually a subclass. |
|
8 |
* |
|
9 |
* @author Mark Sinke |
|
10 |
*/ |
|
11 |
public class OptionDef { |
|
12 |
private final String usage; |
|
13 |
private final String metaVar; |
|
14 |
private final boolean required; |
|
15 |
private final boolean multiValued; |
|
16 |
private final Class<? extends OptionHandler> handler; |
|
17 |
|
|
18 |
public OptionDef(Argument a, boolean forceMultiValued) { |
|
19 |
this(a.usage(), a.metaVar(), a.required(), a.handler(), a.multiValued() || forceMultiValued); |
|
20 |
} |
|
21 |
|
|
22 |
protected OptionDef(String usage, String metaVar, boolean required, |
|
23 |
Class<? extends OptionHandler> handler, boolean multiValued) { |
|
24 |
this.usage = usage; |
|
25 |
this.metaVar = metaVar; |
|
26 |
this.required = required; |
|
27 |
this.handler = handler; |
|
28 |
this.multiValued = multiValued; |
|
29 |
} |
|
30 |
|
|
31 |
public String usage() { |
|
32 |
return usage; |
|
33 |
} |
|
34 |
|
|
35 |
public String metaVar() { |
|
36 |
return metaVar; |
|
37 |
} |
|
38 |
|
|
39 |
public boolean required() { |
|
40 |
return required; |
|
41 |
} |
|
42 |
|
|
43 |
public Class<? extends OptionHandler> handler() { |
|
44 |
return handler; |
|
45 |
} |
|
46 |
|
|
47 |
public boolean isMultiValued() { |
|
48 |
return multiValued; |
|
49 |
} |
|
50 |
|
|
51 |
public boolean isArgument() { |
|
52 |
return true; |
|
53 |
} |
|
54 |
|
|
55 |
@Override |
|
56 |
public String toString() { |
|
57 |
return metaVar() != null ? metaVar() : "ARG"; //$NON-NLS-1$ |
|
58 |
} |
|
59 |
} |
|
0 | 60 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/CmdLineParser.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import java.io.File; |
|
4 |
import java.io.OutputStream; |
|
5 |
import java.io.OutputStreamWriter; |
|
6 |
import java.io.PrintWriter; |
|
7 |
import java.io.Writer; |
|
8 |
import java.lang.reflect.Constructor; |
|
9 |
import java.lang.reflect.InvocationTargetException; |
|
10 |
import java.net.URI; |
|
11 |
import java.net.URL; |
|
12 |
import java.util.ArrayList; |
|
13 |
import java.util.Arrays; |
|
14 |
import java.util.Collection; |
|
15 |
import java.util.Collections; |
|
16 |
import java.util.Date; |
|
17 |
import java.util.HashMap; |
|
18 |
import java.util.HashSet; |
|
19 |
import java.util.List; |
|
20 |
import java.util.Map; |
|
21 |
import java.util.ResourceBundle; |
|
22 |
import java.util.Set; |
|
23 |
import java.util.TreeMap; |
|
24 |
import java.util.logging.Logger; |
|
25 |
|
|
26 |
import org.kohsuke.args4j.spi.BooleanOptionHandler; |
|
27 |
import org.kohsuke.args4j.spi.ByteOptionHandler; |
|
28 |
import org.kohsuke.args4j.spi.CharOptionHandler; |
|
29 |
import org.kohsuke.args4j.spi.DateOptionHandler; |
|
30 |
import org.kohsuke.args4j.spi.DoubleOptionHandler; |
|
31 |
import org.kohsuke.args4j.spi.EnumOptionHandler; |
|
32 |
import org.kohsuke.args4j.spi.FileOptionHandler; |
|
33 |
import org.kohsuke.args4j.spi.FloatOptionHandler; |
|
34 |
import org.kohsuke.args4j.spi.IntOptionHandler; |
|
35 |
import org.kohsuke.args4j.spi.LongOptionHandler; |
|
36 |
import org.kohsuke.args4j.spi.MapOptionHandler; |
|
37 |
import org.kohsuke.args4j.spi.ObjectOptionHandler; |
|
38 |
import org.kohsuke.args4j.spi.OptionHandler; |
|
39 |
import org.kohsuke.args4j.spi.Parameters; |
|
40 |
import org.kohsuke.args4j.spi.QueryOptionHandler; |
|
41 |
import org.kohsuke.args4j.spi.Setter; |
|
42 |
import org.kohsuke.args4j.spi.ShortOptionHandler; |
|
43 |
import org.kohsuke.args4j.spi.StringOptionHandler; |
|
44 |
import org.kohsuke.args4j.spi.URIOptionHandler; |
|
45 |
import org.kohsuke.args4j.spi.URLOptionHandler; |
|
46 |
import org.txm.searchengine.cqp.corpus.query.Query; |
|
47 |
|
|
48 |
|
|
49 |
/** |
|
50 |
* Command line argument owner. |
|
51 |
* |
|
52 |
* <p> |
|
53 |
* For a typical usage, see <a href="https://args4j.dev.java.net/source/browse/args4j/args4j/examples/SampleMain.java?view=markup">this example</a>. |
|
54 |
* |
|
55 |
* @author |
|
56 |
* Kohsuke Kawaguchi (kk@kohsuke.org) |
|
57 |
*/ |
|
58 |
public class CmdLineParser { |
|
59 |
/** |
|
60 |
* Discovered {@link OptionHandler}s for options. |
|
61 |
*/ |
|
62 |
private final List<OptionHandler> options = new ArrayList<OptionHandler>(); |
|
63 |
|
|
64 |
/** |
|
65 |
* Discovered {@link OptionHandler}s for arguments. |
|
66 |
*/ |
|
67 |
private final List<OptionHandler> arguments = new ArrayList<OptionHandler>(); |
|
68 |
|
|
69 |
private boolean parsingOptions = true; |
|
70 |
private OptionHandler currentOptionHandler = null; |
|
71 |
|
|
72 |
/** |
|
73 |
* The length of a usage line. |
|
74 |
* If the usage message is longer than this value, the parser |
|
75 |
* wraps the line. Defaults to 80. |
|
76 |
*/ |
|
77 |
private int usageWidth = 80; |
|
78 |
|
|
79 |
/** |
|
80 |
* Creates a new command line owner that |
|
81 |
* parses arguments/options and set them into |
|
82 |
* the given object. |
|
83 |
* |
|
84 |
* @param bean |
|
85 |
* instance of a class annotated by {@link Option} and {@link Argument}. |
|
86 |
* this object will receive values. If this is null, the processing will |
|
87 |
* be skipped, which is useful if you'd like to feed metadata from other sources. |
|
88 |
* |
|
89 |
* @throws IllegalAnnotationError |
|
90 |
* if the option bean class is using args4j annotations incorrectly. |
|
91 |
*/ |
|
92 |
public CmdLineParser(Object bean) { |
|
93 |
// A 'return' in the constructor just skips the rest of the implementation |
|
94 |
// and returns the new object directly. |
|
95 |
if (bean==null) return; |
|
96 |
|
|
97 |
// Parse the metadata and create the setters |
|
98 |
new ClassParser().parse(bean,this); |
|
99 |
|
|
100 |
// for display purposes, we like the arguments in argument order, but the options in alphabetical order |
|
101 |
/*Collections.sort(options, new Comparator<OptionHandler>() { |
|
102 |
public int compare(OptionHandler o1, OptionHandler o2) { |
|
103 |
return o1.option.toString().compareTo(o2.option.toString()); |
|
104 |
} |
|
105 |
});*/ |
|
106 |
} |
|
107 |
|
|
108 |
/** |
|
109 |
* Programmatically defines an argument (instead of reading it from annotations like you normally do.) |
|
110 |
* |
|
111 |
* @param setter the setter for the type |
|
112 |
* @param a the Argument |
|
113 |
*/ |
|
114 |
public void addArgument(Setter setter, Argument a) { |
|
115 |
OptionHandler h = createOptionHandler(new OptionDef(a,setter.isMultiValued()),setter); |
|
116 |
int index = a.index(); |
|
117 |
// make sure the argument will fit in the list |
|
118 |
while (index >= arguments.size()) { |
|
119 |
arguments.add(null); |
|
120 |
} |
|
121 |
if(arguments.get(index)!=null) { |
|
122 |
throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_ARGUMENT.format(index)); |
|
123 |
} |
|
124 |
arguments.set(index,h); |
|
125 |
} |
|
126 |
|
|
127 |
/** |
|
128 |
* Programmatically defines an option (instead of reading it from annotations like you normally do.) |
|
129 |
* |
|
130 |
* @param setter the setter for the type |
|
131 |
* @param o the Option |
|
132 |
*/ |
|
133 |
public void addOption(Setter setter, Option o) { |
|
134 |
checkOptionNotInMap(o.name()); |
|
135 |
checkWidgetNotInMap(o.widget()); |
|
136 |
for (String alias : o.aliases()) { |
|
137 |
checkOptionNotInMap(alias); |
|
138 |
} |
|
139 |
options.add(createOptionHandler(new NamedOptionDef(o, setter.isMultiValued()), setter)); |
|
140 |
} |
|
141 |
|
|
142 |
public List<OptionHandler> getArguments() { |
|
143 |
return arguments; |
|
144 |
} |
|
145 |
|
|
146 |
public List<OptionHandler> getOptions() { |
|
147 |
return options; |
|
148 |
} |
|
149 |
|
|
150 |
private void checkOptionNotInMap(String name) throws IllegalAnnotationError { |
|
151 |
if(findOptionByName(name)!=null) { |
|
152 |
throw new IllegalAnnotationError(Messages.MULTIPLE_USE_OF_OPTION.format(name)); |
|
153 |
} |
|
154 |
} |
|
155 |
|
|
156 |
public static List<String> widgets = Arrays.asList("Query", "Integer", "File", "CreateFile", "FileSave", "FileOpen", "Folder", "StringArray", "StringArrayMultiple", "StructuralUnits" , "String", "Text", "Float", "Boolean", "Date", "Date-Time"); |
|
157 |
private void checkWidgetNotInMap(String widget) throws IllegalAnnotationError { |
|
158 |
if(!widgets.contains(widget)) { |
|
159 |
throw new IllegalAnnotationError(Messages.UNDEFINNED_WIDGET.format(widget, widgets)); |
|
160 |
} |
|
161 |
} |
|
162 |
|
|
163 |
/** |
|
164 |
* Creates an {@link OptionHandler} that handles the given {@link Option} annotation |
|
165 |
* and the {@link Setter} instance. |
|
166 |
*/ |
|
167 |
@SuppressWarnings("unchecked") |
|
168 |
protected OptionHandler createOptionHandler(OptionDef o, Setter setter) { |
|
169 |
|
|
170 |
Constructor<? extends OptionHandler> handlerType; |
|
171 |
Class<? extends OptionHandler> h = o.handler(); |
|
172 |
|
|
173 |
if(h==OptionHandler.class) { |
|
174 |
// infer the type |
|
175 |
|
|
176 |
// enum is the special case |
|
177 |
Class t = setter.getType(); |
|
178 |
if(Enum.class.isAssignableFrom(t)) |
|
179 |
return new EnumOptionHandler(this,o,setter,t); |
|
180 |
|
|
181 |
handlerType = handlerClasses.get(t); |
|
182 |
if(handlerType==null) |
|
183 |
throw new IllegalAnnotationError(Messages.UNKNOWN_HANDLER.format(t)); |
|
184 |
} else { |
|
185 |
handlerType = getConstructor(h); |
|
186 |
} |
|
187 |
|
|
188 |
try { |
|
189 |
return handlerType.newInstance(this,o,setter); |
|
190 |
} catch (InstantiationException e) { |
|
191 |
throw new IllegalAnnotationError(e); |
|
192 |
} catch (IllegalAccessException e) { |
|
193 |
throw new IllegalAnnotationError(e); |
|
194 |
} catch (InvocationTargetException e) { |
|
195 |
throw new IllegalAnnotationError(e); |
|
196 |
} |
|
197 |
} |
|
198 |
|
|
199 |
/** |
|
200 |
* Formats a command line example into a string. |
|
201 |
* |
|
202 |
* See {@link #printExample(ExampleMode, ResourceBundle)} for more details. |
|
203 |
* |
|
204 |
* @param mode |
|
205 |
* must not be null. |
|
206 |
* @return |
|
207 |
* always non-null. |
|
208 |
*/ |
|
209 |
public String printExample(ExampleMode mode) { |
|
210 |
return printExample(mode,null); |
|
211 |
} |
|
212 |
|
|
213 |
/** |
|
214 |
* Formats a command line example into a string. |
|
215 |
* |
|
216 |
* <p> |
|
217 |
* This method produces a string like " -d <dir> -v -b", |
|
218 |
* which is useful for printing a command line example, perhaps |
|
219 |
* as a part of the usage screen. |
|
220 |
* |
|
221 |
* |
|
222 |
* @param mode |
|
223 |
* One of the {@link ExampleMode} constants. Must not be null. |
|
224 |
* This determines what option should be a part of the returned string. |
|
225 |
* @param rb |
|
226 |
* If non-null, meta variables (<dir> in the above example) |
|
227 |
* is treated as a key to this resource bundle, and the associated |
|
228 |
* value is printed. See {@link Option#metaVar()}. This is to support |
|
229 |
* localization. |
|
230 |
* |
|
231 |
* Passing <tt>null</tt> would print {@link Option#metaVar()} directly. |
|
232 |
* @return |
|
233 |
* always non-null. If there's no option, this method returns |
|
234 |
* just the empty string "". Otherwise, this method returns a |
|
235 |
* string that contains a space at the beginning (but not at the end.) |
|
236 |
* This allows you to do something like: |
|
237 |
* |
|
238 |
* <pre>System.err.println("java -jar my.jar"+parser.printExample(REQUIRED)+" arg1 arg2");</pre> |
|
239 |
*/ |
|
240 |
public String printExample(ExampleMode mode,ResourceBundle rb) { |
|
241 |
StringBuilder buf = new StringBuilder(); |
|
242 |
|
|
243 |
for (OptionHandler h : options) { |
|
244 |
OptionDef option = h.option; |
|
245 |
if(option.usage().length()==0) continue; // ignore |
|
246 |
if(!mode.print(option)) continue; |
|
247 |
|
|
248 |
buf.append(' '); |
|
249 |
buf.append(h.getNameAndMeta(rb)); |
|
250 |
} |
|
251 |
|
|
252 |
return buf.toString(); |
|
253 |
} |
|
254 |
|
|
255 |
/** |
|
256 |
* Prints the list of options and their usages to the screen. |
|
257 |
* |
|
258 |
* <p> |
|
259 |
* This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)} |
|
260 |
* so that you can do {@code printUsage(System.err)}. |
|
261 |
*/ |
|
262 |
public void printUsage(OutputStream out) { |
|
263 |
printUsage(new OutputStreamWriter(out),null); |
|
264 |
} |
|
265 |
|
|
266 |
/** |
|
267 |
* Prints the list of options and their usages to the screen. |
|
268 |
* |
|
269 |
* @param rb |
|
270 |
* if this is non-null, {@link Option#usage()} is treated |
|
271 |
* as a key to obtain the actual message from this resource bundle. |
|
272 |
*/ |
|
273 |
public void printUsage(Writer out, ResourceBundle rb) { |
|
274 |
PrintWriter w = new PrintWriter(out); |
|
275 |
// determine the length of the option + metavar first |
|
276 |
int len = 0; |
|
277 |
for (OptionHandler h : arguments) { |
|
278 |
int curLen = getPrefixLen(h, rb); |
|
279 |
len = Math.max(len,curLen); |
|
280 |
} |
|
281 |
for (OptionHandler h: options) { |
|
282 |
int curLen = getPrefixLen(h, rb); |
|
283 |
len = Math.max(len,curLen); |
|
284 |
} |
|
285 |
|
|
286 |
// then print |
|
287 |
for (OptionHandler h : arguments) { |
|
288 |
printOption(w, h, len, rb); |
|
289 |
} |
|
290 |
for (OptionHandler h : options) { |
|
291 |
printOption(w, h, len, rb); |
|
292 |
} |
|
293 |
|
|
294 |
w.flush(); |
|
295 |
} |
|
296 |
|
|
297 |
/** |
|
298 |
* Prints the usage information for a given option. |
|
299 |
* @param out Writer to write into |
|
300 |
* @param handler handler where to receive the informations |
|
301 |
* @param len Maximum length of metadata column |
|
302 |
* @param rb ResourceBundle for I18N |
|
303 |
*/ |
|
304 |
private void printOption(PrintWriter out, OptionHandler handler, int len, ResourceBundle rb) { |
|
305 |
// Hiding options without usage information |
|
306 |
if (handler.option.usage() == null || handler.option.usage().length() == 0) { |
|
307 |
return; |
|
308 |
} |
|
309 |
|
|
310 |
// What is the width of the two data columns |
|
311 |
int widthMetadata = Math.min(len, (usageWidth - 4) / 2); |
|
312 |
int widthUsage = usageWidth - 4 - widthMetadata; |
|
313 |
|
|
314 |
// Line wrapping |
|
315 |
List<String> namesAndMetas = wrapLines(handler.getNameAndMeta(rb), widthMetadata); |
|
316 |
List<String> usages = wrapLines(localize(handler.option.usage(),rb), widthUsage); |
|
317 |
|
|
318 |
// Output |
|
319 |
for(int i=0; i<Math.max(namesAndMetas.size(), usages.size()); i++) { |
|
320 |
String nameAndMeta = (i >= namesAndMetas.size()) ? "" : namesAndMetas.get(i); |
|
321 |
String usage = (i >= usages.size()) ? "" : usages.get(i); |
|
322 |
String format = (nameAndMeta.length() > 0) |
|
323 |
? " %1$-" + widthMetadata + "s : %2$-1s" |
|
324 |
: " %1$-" + widthMetadata + "s %2$-1s"; |
|
325 |
String output = String.format(format, nameAndMeta, usage); |
|
326 |
out.println(output); |
|
327 |
} |
|
328 |
} |
|
329 |
|
|
330 |
private String localize(String s, ResourceBundle rb) { |
|
331 |
if(rb!=null) return rb.getString(s); |
|
332 |
return s; |
|
333 |
} |
|
334 |
|
|
335 |
/** |
|
336 |
* Wraps a line so that the resulting parts are not longer than a given maximum length. |
|
337 |
* @param line Line to wrap |
|
338 |
* @param maxLength maximum length for the resulting parts |
|
339 |
* @return list of all wrapped parts |
|
340 |
*/ |
|
341 |
private List<String> wrapLines(String line, final int maxLength) { |
|
342 |
List<String> rv = new ArrayList<String>(); |
|
343 |
for (String restOfLine : line.split("\\n")) { |
|
344 |
while (restOfLine.length() > maxLength) { |
|
345 |
// try to wrap at space, but don't try too hard as some languages don't even have whitespaces. |
|
346 |
int lineLength; |
|
347 |
String candidate = restOfLine.substring(0, maxLength); |
|
348 |
int sp=candidate.lastIndexOf(' '); |
|
349 |
if(sp>maxLength*3/4) lineLength=sp; |
|
350 |
else lineLength=maxLength; |
|
351 |
rv.add(restOfLine.substring(0, lineLength)); |
|
352 |
restOfLine = restOfLine.substring(lineLength).trim(); |
|
353 |
} |
|
354 |
rv.add(restOfLine); |
|
355 |
} |
|
356 |
return rv; |
|
357 |
} |
|
358 |
|
|
359 |
private int getPrefixLen(OptionHandler h, ResourceBundle rb) { |
|
360 |
if(h.option.usage().length()==0) |
|
361 |
return 0; |
|
362 |
|
|
363 |
return h.getNameAndMeta(rb).length(); |
|
364 |
} |
|
365 |
|
|
366 |
/** |
|
367 |
* Essentially a pointer over a {@link String} array. |
|
368 |
* Can move forward, can look ahead. |
|
369 |
*/ |
|
370 |
private class CmdLineImpl implements Parameters { |
|
371 |
private final String[] args; |
|
372 |
private int pos; |
|
373 |
|
|
374 |
CmdLineImpl( String[] args ) { |
|
375 |
this.args = args; |
|
376 |
pos = 0; |
|
377 |
} |
|
378 |
|
|
379 |
protected boolean hasMore() { |
|
380 |
return pos<args.length; |
|
381 |
} |
|
382 |
|
|
383 |
protected String getCurrentToken() { |
|
384 |
return args[pos]; |
|
385 |
} |
|
386 |
|
|
387 |
private void proceed( int n ) { |
|
388 |
pos += n; |
|
389 |
} |
|
390 |
|
|
391 |
public String getParameter(int idx) throws CmdLineException { |
|
392 |
if( pos+idx>=args.length ) |
|
393 |
throw new CmdLineException(CmdLineParser.this, Messages.MISSING_OPERAND.format(getOptionName())); |
|
394 |
return args[pos+idx]; |
|
395 |
} |
|
396 |
|
|
397 |
public int size() { |
|
398 |
return args.length-pos; |
|
399 |
} |
|
400 |
} |
|
401 |
|
|
402 |
private String getOptionName() { |
|
403 |
return currentOptionHandler.option.toString(); |
|
404 |
} |
|
405 |
|
|
406 |
/** |
|
407 |
* Same as {@link #parseArgument(String[])} |
|
408 |
*/ |
|
409 |
public void parseArgument(Collection<String> args) throws CmdLineException { |
|
410 |
parseArgument(args.toArray(new String[args.size()])); |
|
411 |
} |
|
412 |
|
|
413 |
/** |
|
414 |
* Parses the command line arguments and set them to the option bean |
|
415 |
* given in the constructor. |
|
416 |
* |
|
417 |
* @param args arguments to parse |
|
418 |
* |
|
419 |
* @throws CmdLineException |
|
420 |
* if there's any error parsing arguments, or if |
|
421 |
* {@link Option#required() required} option was not given. |
|
422 |
*/ |
|
423 |
public void parseArgument(final String... args) throws CmdLineException { |
|
424 |
CmdLineImpl cmdLine = new CmdLineImpl(args); |
|
425 |
|
|
426 |
Set<OptionHandler> present = new HashSet<OptionHandler>(); |
|
427 |
int argIndex = 0; |
|
428 |
|
|
429 |
while( cmdLine.hasMore() ) { |
|
430 |
String arg = cmdLine.getCurrentToken(); |
|
431 |
if( isOption(arg) ) { |
|
432 |
boolean isKeyValuePair = arg.indexOf('=')!=-1; |
|
433 |
// parse this as an option. |
|
434 |
currentOptionHandler = isKeyValuePair ? findOptionHandler(arg) : findOptionByName(arg); |
|
435 |
|
|
436 |
if(currentOptionHandler==null) { |
|
437 |
// TODO: insert dynamic handler processing |
|
438 |
throw new CmdLineException(this, Messages.UNDEFINED_OPTION.format(arg)); |
|
439 |
} |
|
440 |
|
|
441 |
// known option; skip its name |
|
442 |
cmdLine.proceed(1); |
|
443 |
} else { |
|
444 |
if (argIndex >= arguments.size()) { |
|
445 |
Messages msg = arguments.size() == 0 ? Messages.NO_ARGUMENT_ALLOWED : Messages.TOO_MANY_ARGUMENTS; |
|
446 |
throw new CmdLineException(this, msg.format(arg)); |
|
447 |
} |
|
448 |
|
|
449 |
// known argument |
|
450 |
currentOptionHandler = arguments.get(argIndex); |
|
451 |
if (!currentOptionHandler.option.isMultiValued()) |
|
452 |
argIndex++; |
|
453 |
} |
|
454 |
int diff = currentOptionHandler.parseArguments(cmdLine); |
|
455 |
cmdLine.proceed(diff); |
|
456 |
present.add(currentOptionHandler); |
|
457 |
} |
|
458 |
|
|
459 |
// make sure that all mandatory options are present |
|
460 |
for (OptionHandler handler : options) |
|
461 |
if(handler.option.required() && !present.contains(handler)) |
|
462 |
throw new CmdLineException(this, Messages.REQUIRED_OPTION_MISSING.format(handler.option.toString())); |
|
463 |
|
|
464 |
// make sure that all mandatory arguments are present |
|
465 |
for (OptionHandler handler : arguments) |
|
466 |
if(handler.option.required() && !present.contains(handler)) |
|
467 |
throw new CmdLineException(this, Messages.REQUIRED_ARGUMENT_MISSING.format(handler.option.toString())); |
|
468 |
} |
|
469 |
|
|
470 |
private OptionHandler findOptionHandler(String name) { |
|
471 |
OptionHandler handler = findOptionByName(name); |
|
472 |
if (handler==null) { |
|
473 |
// Have not found by its name, maybe its a property? |
|
474 |
// Search for parts of the name (=prefix) - most specific first |
|
475 |
for (int i=name.length(); i>1; i--) { |
|
476 |
String prefix = name.substring(0, i); |
|
477 |
Map<String,OptionHandler> possibleHandlers = filter(options, prefix); |
|
478 |
handler = possibleHandlers.get(prefix); |
|
479 |
if (handler!=null) return handler; |
|
480 |
} |
|
481 |
} |
|
482 |
return handler; |
|
483 |
} |
|
484 |
|
|
485 |
/** |
|
486 |
* Finds a registered OptionHandler by its name or its alias. |
|
487 |
* @param name name |
|
488 |
* @return the OptionHandler or <tt>null</tt> |
|
489 |
*/ |
|
490 |
private OptionHandler findOptionByName(String name) { |
|
491 |
for (OptionHandler h : options) { |
|
492 |
NamedOptionDef option = (NamedOptionDef)h.option; |
|
493 |
if (name.equals(option.name())) { |
|
494 |
return h; |
|
495 |
} |
|
496 |
for (String alias : option.aliases()) { |
|
497 |
if (name.equals(alias)) { |
|
498 |
return h; |
|
499 |
} |
|
500 |
} |
|
501 |
} |
|
502 |
return null; |
|
503 |
} |
|
504 |
|
|
505 |
|
|
506 |
private Map<String,OptionHandler> filter(List<OptionHandler> opt, String keyFilter) { |
|
507 |
Map<String,OptionHandler> rv = new TreeMap<String,OptionHandler>(); |
|
508 |
for (OptionHandler h : opt) { |
|
509 |
if (opt.toString().startsWith(keyFilter)) rv.put(opt.toString(), h); |
|
510 |
} |
|
511 |
return rv; |
|
512 |
} |
|
513 |
|
|
514 |
|
|
515 |
/** |
|
516 |
* Returns true if the given token is an option |
|
517 |
* (as opposed to an argument.) |
|
518 |
*/ |
|
519 |
protected boolean isOption(String arg) { |
|
520 |
return parsingOptions && arg.startsWith("-"); |
|
521 |
} |
|
522 |
|
|
523 |
|
|
524 |
/** |
|
525 |
* All {@link OptionHandler}s known to the {@link CmdLineParser}. |
|
526 |
* |
|
527 |
* Constructors of {@link OptionHandler}-derived class keyed by their supported types. |
|
528 |
*/ |
|
529 |
private static final Map<Class,Constructor<? extends OptionHandler>> handlerClasses = |
|
530 |
Collections.synchronizedMap(new HashMap<Class,Constructor<? extends OptionHandler>>()); |
|
531 |
|
|
532 |
/** |
|
533 |
* Registers a user-defined {@link OptionHandler} class with args4j. |
|
534 |
* |
|
535 |
* <p> |
|
536 |
* This method allows users to extend the behavior of args4j by writing |
|
537 |
* their own {@link OptionHandler} implementation. |
|
538 |
* |
|
539 |
* @param valueType |
|
540 |
* The specified handler is used when the field/method annotated by {@link Option} |
|
541 |
* is of this type. |
|
542 |
* @param handlerClass |
|
543 |
* This class must have the constructor that has the same signature as |
|
544 |
* {@link OptionHandler#OptionHandler(CmdLineParser, OptionDef, Setter)} |
|
545 |
*/ |
|
546 |
public static void registerHandler( Class valueType, Class<? extends OptionHandler> handlerClass ) { |
|
547 |
if(valueType==null || handlerClass==null) |
|
548 |
throw new IllegalArgumentException(); |
|
549 |
if(!OptionHandler.class.isAssignableFrom(handlerClass)) |
|
550 |
throw new IllegalArgumentException(Messages.NO_OPTIONHANDLER.format()); |
|
551 |
|
|
552 |
Constructor<? extends OptionHandler> c = getConstructor(handlerClass); |
|
553 |
handlerClasses.put(valueType,c); |
|
554 |
} |
|
555 |
|
|
556 |
private static Constructor<? extends OptionHandler> getConstructor(Class<? extends OptionHandler> handlerClass) { |
|
557 |
try { |
|
558 |
return handlerClass.getConstructor(CmdLineParser.class, OptionDef.class, Setter.class); |
|
559 |
} catch (NoSuchMethodException e) { |
|
560 |
throw new IllegalArgumentException(Messages.NO_CONSTRUCTOR_ON_HANDLER.format(handlerClass)); |
|
561 |
} |
|
562 |
} |
|
563 |
|
|
564 |
static { |
|
565 |
registerHandler(Boolean.class,BooleanOptionHandler.class); |
|
566 |
registerHandler(boolean.class,BooleanOptionHandler.class); |
|
567 |
registerHandler(File.class,FileOptionHandler.class); |
|
568 |
registerHandler(URL.class, URLOptionHandler.class); |
|
569 |
registerHandler(URI.class, URIOptionHandler.class); |
|
570 |
registerHandler(Integer.class,IntOptionHandler.class); |
|
571 |
registerHandler(int.class,IntOptionHandler.class); |
|
572 |
registerHandler(Double.class, DoubleOptionHandler.class); |
|
573 |
registerHandler(double.class,DoubleOptionHandler.class); |
|
574 |
registerHandler(String.class,StringOptionHandler.class); |
|
575 |
registerHandler(Byte.class, ByteOptionHandler.class); |
|
576 |
registerHandler(byte.class, ByteOptionHandler.class); |
|
577 |
registerHandler(Character.class, CharOptionHandler.class); |
|
578 |
registerHandler(char.class, CharOptionHandler.class); |
|
579 |
registerHandler(Float.class, FloatOptionHandler.class); |
|
580 |
registerHandler(float.class, FloatOptionHandler.class); |
|
581 |
registerHandler(Long.class, LongOptionHandler.class); |
|
582 |
registerHandler(long.class, LongOptionHandler.class); |
|
583 |
registerHandler(Short.class, ShortOptionHandler.class); |
|
584 |
registerHandler(short.class, ShortOptionHandler.class); |
|
585 |
registerHandler(Date.class, DateOptionHandler.class); |
|
586 |
registerHandler(Query.class, QueryOptionHandler.class); |
|
587 |
registerHandler(Object.class, ObjectOptionHandler.class); |
|
588 |
// enum is a special case |
|
589 |
registerHandler(Map.class,MapOptionHandler.class); |
|
590 |
} |
|
591 |
|
|
592 |
public void setUsageWidth(int usageWidth) { |
|
593 |
this.usageWidth = usageWidth; |
|
594 |
} |
|
595 |
|
|
596 |
public void stopOptionParsing() { |
|
597 |
parsingOptions = false; |
|
598 |
} |
|
599 |
|
|
600 |
/** |
|
601 |
* Prints a single-line usage to the screen. |
|
602 |
* |
|
603 |
* <p> |
|
604 |
* This is a convenience method for calling {@code printUsage(new OutputStreamWriter(out),null)} |
|
605 |
* so that you can do {@code printUsage(System.err)}. |
|
606 |
*/ |
|
607 |
public void printSingleLineUsage(OutputStream out) { |
|
608 |
printSingleLineUsage(new OutputStreamWriter(out),null); |
|
609 |
} |
|
610 |
|
|
611 |
/** |
|
612 |
* Prints a single-line usage to the screen. |
|
613 |
* |
|
614 |
* @param rb |
|
615 |
* if this is non-null, {@link Option#usage()} is treated |
|
616 |
* as a key to obtain the actual message from this resource bundle. |
|
617 |
*/ |
|
618 |
public void printSingleLineUsage(Writer w, ResourceBundle rb) { |
|
619 |
PrintWriter pw = new PrintWriter(w); |
|
620 |
for (OptionHandler h : arguments) { |
|
621 |
printSingleLineOption(pw, h, rb); |
|
622 |
} |
|
623 |
for (OptionHandler h : options) { |
|
624 |
printSingleLineOption(pw, h, rb); |
|
625 |
} |
|
626 |
pw.flush(); |
|
627 |
} |
|
628 |
|
|
629 |
private void printSingleLineOption(PrintWriter pw, OptionHandler h, ResourceBundle rb) { |
|
630 |
pw.print(' '); |
|
631 |
if (!h.option.required()) |
|
632 |
pw.print('['); |
|
633 |
pw.print(h.getNameAndMeta(rb)); |
|
634 |
if (h.option.isMultiValued()) { |
|
635 |
pw.print(" ..."); |
|
636 |
} |
|
637 |
if (!h.option.required()) |
|
638 |
pw.print(']'); |
|
639 |
} |
|
640 |
|
|
641 |
private static final Logger LOGGER = Logger.getLogger(CmdLineParser.class.getName()); |
|
642 |
} |
|
0 | 643 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/CmdLineException.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
import org.kohsuke.args4j.spi.OptionHandler; |
|
4 |
|
|
5 |
/** |
|
6 |
* Signals an error in the user input. |
|
7 |
* |
|
8 |
* @author Kohsuke Kawaguchi |
|
9 |
*/ |
|
10 |
public class CmdLineException extends Exception { |
|
11 |
private static final long serialVersionUID = -8574071211991372980L; |
|
12 |
|
|
13 |
private CmdLineParser parser; |
|
14 |
|
|
15 |
/** |
|
16 |
* @deprecated |
|
17 |
* Use {@link #CmdLineException(CmdLineParser, String)} |
|
18 |
*/ |
|
19 |
public CmdLineException(String message) { |
|
20 |
super(message); |
|
21 |
} |
|
22 |
|
|
23 |
/** |
|
24 |
* @deprecated |
|
25 |
* Use {@link #CmdLineException(CmdLineParser, String, Throwable)} |
|
26 |
*/ |
|
27 |
public CmdLineException(String message, Throwable cause) { |
|
28 |
super(message, cause); |
|
29 |
} |
|
30 |
|
|
31 |
/** |
|
32 |
* @deprecated |
|
33 |
* Use {@link #CmdLineException(CmdLineParser, Throwable)} |
|
34 |
*/ |
|
35 |
public CmdLineException(Throwable cause) { |
|
36 |
super(cause); |
|
37 |
} |
|
38 |
|
|
39 |
public CmdLineException(CmdLineParser parser, String message) { |
|
40 |
super(message); |
|
41 |
this.parser = parser; |
|
42 |
} |
|
43 |
|
|
44 |
public CmdLineException(CmdLineParser parser, String message, Throwable cause) { |
|
45 |
super(message, cause); |
|
46 |
this.parser = parser; |
|
47 |
} |
|
48 |
|
|
49 |
public CmdLineException(CmdLineParser parser, Throwable cause) { |
|
50 |
super(cause); |
|
51 |
this.parser = parser; |
|
52 |
} |
|
53 |
|
|
54 |
/** |
|
55 |
* Obtains the {@link CmdLineParser} that triggered an exception. |
|
56 |
* |
|
57 |
* <p> |
|
58 |
* Unless you have legacy {@link OptionHandler} that doesn't pass in this information |
|
59 |
* when it throws an exception, this method should always return a non-null value. a |
|
60 |
*/ |
|
61 |
public CmdLineParser getParser() { |
|
62 |
return parser; |
|
63 |
} |
|
64 |
} |
|
0 | 65 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/NamedOptionDef.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
/** |
|
4 |
* Run-time copy of the Option or Argument annotation. |
|
5 |
*/ |
|
6 |
public final class NamedOptionDef extends OptionDef { |
|
7 |
private final String name; |
|
8 |
private final String def; |
|
9 |
private final String widget; |
|
10 |
private final String[] aliases; |
|
11 |
|
|
12 |
public NamedOptionDef(Option o, boolean forceMultiValued) { |
|
13 |
super(o.usage(),o.metaVar(),o.required(),o.handler(),o.multiValued() || forceMultiValued); |
|
14 |
|
|
15 |
this.name = o.name(); |
|
16 |
this.def = o.def(); |
|
17 |
this.widget = o.widget(); |
|
18 |
this.aliases = o.aliases(); |
|
19 |
} |
|
20 |
|
|
21 |
public String name() { |
|
22 |
return name; |
|
23 |
} |
|
24 |
|
|
25 |
public String def() { |
|
26 |
return def; |
|
27 |
} |
|
28 |
|
|
29 |
public String widget() { |
|
30 |
return widget; |
|
31 |
} |
|
32 |
|
|
33 |
public String[] aliases() { |
|
34 |
return aliases; |
|
35 |
} |
|
36 |
|
|
37 |
@Override |
|
38 |
public String toString() { |
|
39 |
if (aliases.length > 0) { |
|
40 |
String str = ""; //$NON-NLS-1$ |
|
41 |
for (String alias : aliases) { |
|
42 |
if (str.length() > 0) { |
|
43 |
str += ", "; //$NON-NLS-1$ |
|
44 |
} |
|
45 |
str += alias; |
|
46 |
} |
|
47 |
return name() + " widget="+widget()+" (" + str + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
48 |
} |
|
49 |
return name(); |
|
50 |
} |
|
51 |
|
|
52 |
@Override |
|
53 |
public boolean isArgument() { |
|
54 |
return false; |
|
55 |
} |
|
56 |
} |
|
0 | 57 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/Messages_ru_RU.properties (revision 890) | ||
---|---|---|
1 |
MISSING_OPERAND = \u041E\u043F\u0446\u0438\u044F "{0}" \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u043D\u0434 |
|
2 |
UNDEFINED_OPTION = "{0}" \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u043F\u0446\u0438\u044F |
|
3 |
NO_ARGUMENT_ALLOWED = \u041D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\: {0} |
|
4 |
REQUIRED_OPTION_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u043E\u043F\u0446\u0438\u044F "{0}" |
|
5 |
REQUIRED_ARGUMENT_MISSING = \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442 "{0}" |
|
6 |
TOO_MANY_ARGUMENTS = \u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u043D\u043E\u0433\u043E \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u0432\: {0} |
|
7 |
|
|
8 |
|
|
9 |
# For translation |
|
10 |
#------------------ |
|
11 |
# METADATA_ERROR = Problems while reading the args-confguration. |
|
12 |
# MULTIPLE_USE_OF_ARGUMENT = Argument with index {0} is used more than once |
|
13 |
# MULTIPLE_USE_OF_OPTION = Option name {0} is used more than once |
|
14 |
# UNKNOWN_HANDLER = No OptionHandler is registered to handle {0} |
|
15 |
# NO_OPTIONHANDLER = Not an OptionHandler class |
|
16 |
# NO_CONSTRUCTOR_ON_HANDLER = {0} does not have the proper constructor |
|
17 |
# FORMAT_ERROR_FOR_MAP = An argument for setting a Map must contain a ''='' |
|
18 |
# MAP_HAS_NO_KEY = A key must be set. |
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
|
0 | 23 |
tmp/org.txm.libs.args4j/src/org/kohsuke/args4j/ExampleMode.java (revision 890) | ||
---|---|---|
1 |
package org.kohsuke.args4j; |
|
2 |
|
|
3 |
/** |
|
4 |
* Used with {@link CmdLineParser#printExample(ExampleMode)}. |
|
5 |
* |
|
6 |
* @author Kohsuke Kawaguchi |
|
7 |
*/ |
|
8 |
public enum ExampleMode { |
|
9 |
/** |
|
10 |
* Print all defined options in the example. |
|
11 |
* |
|
12 |
* <p> |
|
13 |
* This would be useful only when you have small number of options. |
|
14 |
*/ |
|
15 |
ALL() { |
|
16 |
@Override |
|
17 |
/*package*/ boolean print(OptionDef o) { |
|
18 |
return true; |
|
19 |
} |
|
20 |
}, |
|
21 |
|
Formats disponibles : Unified diff