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