You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by xa...@apache.org on 2008/02/29 17:40:57 UTC
svn commit: r632381 - in /ant/ivy/core/trunk: ./ META-INF/ doc/
src/java/org/apache/ivy/ src/java/org/apache/ivy/util/
src/java/org/apache/ivy/util/cli/ test/java/org/apache/ivy/
Author: xavier
Date: Fri Feb 29 08:40:52 2008
New Revision: 632381
URL: http://svn.apache.org/viewvc?rev=632381&view=rev
Log:
IMPROVEMENT: Make Ivy standalone runnable with no required dependencies (IVY-757)
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java (with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java (with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java (with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java (with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java (with props)
ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java (with props)
Modified:
ant/ivy/core/trunk/CHANGES.txt
ant/ivy/core/trunk/META-INF/MANIFEST.MF
ant/ivy/core/trunk/doc/standalone.html
ant/ivy/core/trunk/ivy.xml
ant/ivy/core/trunk/src/java/org/apache/ivy/Main.java
ant/ivy/core/trunk/src/java/org/apache/ivy/util/StringUtils.java
Modified: ant/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Fri Feb 29 08:40:52 2008
@@ -64,6 +64,8 @@
trunk version
=====================================
+- IMPROVEMENT: Make Ivy standalone runnable with no required dependencies (IVY-757)
+
- FIX: PublishEventsTest fails when Ivy sources are located in a directory with a + (IVY-755)
- FIX: XML entity parsing does not work properly (IVY-737) (thanks to Patrick Woodworth)
- FIX: Cachefileset task silently fails with parent dir ".." construct (IVY-638)
Modified: ant/ivy/core/trunk/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/META-INF/MANIFEST.MF?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/META-INF/MANIFEST.MF (original)
+++ ant/ivy/core/trunk/META-INF/MANIFEST.MF Fri Feb 29 08:40:52 2008
@@ -1,4 +1,5 @@
Manifest-Version: 1.0
+Main-Class: org.apache.ivy.Main
Bundle-Version: 0.0.0
Bundle-Name: Ivy
Bundle-ManifestVersion: 2
@@ -15,7 +16,6 @@
com.jcraft.jsch;resolution:=optional,
javax.swing;resolution:=optional,
javax.swing.event;resolution:=optional,
- org.apache.commons.cli;resolution:=optional,
org.apache.commons.httpclient;resolution:=optional,
org.apache.commons.httpclient.methods;resolution:=optional,
org.apache.commons.httpclient.params;resolution:=optional,
Modified: ant/ivy/core/trunk/doc/standalone.html
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/standalone.html?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/standalone.html (original)
+++ ant/ivy/core/trunk/doc/standalone.html Fri Feb 29 08:40:52 2008
@@ -25,13 +25,13 @@
</head>
<body>
<textarea id="xooki-source">
-In the case you want to call ivy as a standalone program (outside from ant), you have to put commons-cli 1.0 and its dependencies in your classpath.
+Ivy can be used as a standalone program very easily. All you need is a java 1.4+ runtime environment (JRE)!
Then here is how to call it:
<code>
-java org.apache.ivy.Main -?
+java -jar ivy.jar -?
</code>
-It will indicate you what can be given as argument.
+It will display an help telling what can be given as argument.
<span class="since">since 1.3</span> System properties are included as ivy variables, so you can easily define an ivy variable like this:
@@ -42,24 +42,24 @@
<h1>Examples</h1>
<code>
-java org.apache.ivy.Main
+java -jar ivy.jar
</code>
calls ivy with default configuration using ivy.xml in the current dir
<hr/>
<code>
-java org.apache.ivy.Main -conf path/to/myivysettings.xml -ivy path/to/myivy.xml
+java -jar ivy.jar -conf path/to/myivysettings.xml -ivy path/to/myivy.xml
</code>
calls ivy with given ivysettings file using given ivy file
<hr/>
<span class="since">since 1.3</span>
<code>
-java org.apache.ivy.Main -conf path/to/myivysettings.xml -dependency apache commons-lang 2.0
+java -jar ivy.jar -conf path/to/myivysettings.xml -dependency apache commons-lang 2.0
</code>
calls ivy with given ivysettings file and resolve apache commons-lang 2.0.
This is equivalent to:
<code>
-java org.apache.ivy.Main -conf path/to/myivysettings.xml -ivy ivy.xml
+java -jar ivy.jar -conf path/to/myivysettings.xml -ivy ivy.xml
</code>
with ivy.xml like this:
<code type="xml">
@@ -76,14 +76,14 @@
<hr/>
<span class="since">since 1.3</span>
<code>
-java org.apache.ivy.Main -conf path/to/myivysettings.xml -ivy path/to/myivy.xml -cachepath mycachefile.txt
+java -jar ivy.jar -conf path/to/myivysettings.xml -ivy path/to/myivy.xml -cachepath mycachefile.txt
</code>
calls ivy with given ivysettings file and resolve the dependencies found in the given ivy file, and then output the classpath of resolved artifacts in cache in a file. This file can then be used to define a classpath corresponding to all the resolved dependencies for any java program.
<hr/>
<span class="since">since 1.4</span>
<code>
-java org.apache.ivy.Main -conf path/to/myivysettings.xml -dependency bar foo 2.0 -main org.bar.foo.FooMain
+java -jar ivy.jar -conf path/to/myivysettings.xml -dependency bar foo 2.0 -main org.bar.foo.FooMain
</code>
calls ivy with given ivysettings file and resolve bar foo 2.0, and then run org.foo.FooMain class with the resolved artifacts as classpath
Modified: ant/ivy/core/trunk/ivy.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/ivy.xml?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/ivy.xml (original)
+++ ant/ivy/core/trunk/ivy.xml Fri Feb 29 08:40:52 2008
@@ -40,7 +40,6 @@
<dependencies>
<dependency org="ant" name="ant" rev="1.6" conf="default,ant->default"/>
<dependency org="commons-httpclient" name="commons-httpclient" rev="3.0" conf="default,httpclient->runtime,master" />
- <dependency org="commons-cli" name="commons-cli" rev="1.0" conf="default,standalone->runtime,master" />
<dependency org="oro" name="oro" rev="2.0.8" conf="default,oro->default"/>
<dependency org="commons-vfs" name="commons-vfs" rev="1.0" conf="default,vfs->default" />
<dependency org="jsch" name="jsch" rev="0.1.25" conf="default,sftp->default" />
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/Main.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/Main.java?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/Main.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/Main.java Fri Feb 29 08:40:52 2008
@@ -35,14 +35,6 @@
import java.util.List;
import java.util.StringTokenizer;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
import org.apache.ivy.core.cache.ResolutionCacheManager;
import org.apache.ivy.core.deliver.DeliverOptions;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
@@ -59,6 +51,10 @@
import org.apache.ivy.plugins.report.XmlReportParser;
import org.apache.ivy.util.DefaultMessageLogger;
import org.apache.ivy.util.Message;
+import org.apache.ivy.util.cli.CommandLine;
+import org.apache.ivy.util.cli.CommandLineParser;
+import org.apache.ivy.util.cli.OptionBuilder;
+import org.apache.ivy.util.cli.ParseException;
import org.apache.ivy.util.url.CredentialsStore;
import org.apache.ivy.util.url.URLHandler;
import org.apache.ivy.util.url.URLHandlerDispatcher;
@@ -70,108 +66,114 @@
* Valid arguments can be obtained with the -? argument.
*/
public final class Main {
- private static final int DEPENDENCY_ARG_COUNT = 3;
+ private static final int HELP_WIDTH = 80;
+ private static PrintWriter out = new PrintWriter(System.out);
- private static Options getOptions() {
- Option settings = OptionBuilder.withArgName("settingsfile").hasArg().withDescription(
- "use given file for settings").create("settings");
- Option conf = OptionBuilder.withArgName("settingsfile").hasArg().withDescription(
- "DEPRECATED - use given file for settings").create("conf");
- Option cache = OptionBuilder.withArgName("cachedir").hasArg().withDescription(
- "use given directory for cache").create("cache");
- Option ivyfile = OptionBuilder.withArgName("ivyfile").hasArg().withDescription(
- "use given file as ivy file").create("ivy");
- Option dependency = OptionBuilder
- .withArgName("organisation module revision")
- .hasArgs()
- .withDescription(
- "use this instead of ivy file to do the rest "
- + "of the work with this as a dependency.")
- .create("dependency");
- Option confs = OptionBuilder.withArgName("configurations").hasArgs().withDescription(
- "resolve given configurations").create("confs");
- Option retrieve = OptionBuilder.withArgName("retrievepattern").hasArg().withDescription(
- "use given pattern as retrieve pattern").create("retrieve");
- Option cachepath = OptionBuilder
- .withArgName("cachepathfile")
- .hasArg()
- .withDescription(
- "outputs a classpath consisting of all dependencies in cache "
+ static CommandLineParser getParser() {
+ return new CommandLineParser()
+ .addCategory("settings options")
+ .addOption(new OptionBuilder("settings").arg("settingsfile")
+ .description("use given file for settings").create())
+ .addOption(new OptionBuilder("cache").arg("cachedir")
+ .description("use given directory for cache").create())
+ .addOption(new OptionBuilder("novalidate")
+ .description("do not validate ivy files against xsd").create())
+ .addOption(new OptionBuilder("m2compatible")
+ .description("use maven2 compatibility").create())
+ .addOption(new OptionBuilder("conf").arg("settingsfile").deprecated()
+ .description("use given file for settings").create())
+ .addOption(new OptionBuilder("useOrigin").deprecated()
+ .description("use original artifact location "
+ + "with local resolvers instead of copying to the cache").create())
+
+ .addCategory("resolve options")
+ .addOption(new OptionBuilder("ivy").arg("ivyfile")
+ .description("use given file as ivy file").create())
+ .addOption(new OptionBuilder("dependency")
+ .arg("organisation").arg("module").arg("revision")
+ .description("use this instead of ivy file to do the rest "
+ + "of the work with this as a dependency.").create())
+ .addOption(new OptionBuilder("confs").arg("configurations").countArgs(false)
+ .description("resolve given configurations").create())
+
+ .addCategory("retrieve options")
+ .addOption(new OptionBuilder("retrieve").arg("retrievepattern")
+ .description("use given pattern as retrieve pattern").create())
+ .addOption(new OptionBuilder("sync")
+ .description("use sync mode for retrieve").create())
+
+ .addCategory("cache path options")
+ .addOption(new OptionBuilder("cachepath").arg("cachepathfile")
+ .description("outputs a classpath consisting of all dependencies in cache "
+ "(including transitive ones) "
- + "of the given ivy file to the given cachepathfile")
- .create("cachepath");
- Option revision = OptionBuilder.withArgName("revision").hasArg().withDescription(
- "use given revision to publish the module").create("revision");
- Option status = OptionBuilder.withArgName("status").hasArg().withDescription(
- "use given status to publish the module").create("status");
- Option deliver = OptionBuilder.withArgName("ivypattern").hasArg().withDescription(
- "use given pattern as resolved ivy file pattern").create("deliverto");
- Option publishResolver = OptionBuilder.withArgName("resolvername").hasArg()
- .withDescription("use given resolver to publish to").create("publish");
- Option publishPattern = OptionBuilder.withArgName("artpattern").hasArg().withDescription(
- "use given pattern to find artifacts to publish").create("publishpattern");
- Option realm = OptionBuilder.withArgName("realm").hasArg().withDescription(
- "use given realm for HTTP AUTH").create("realm");
- Option host = OptionBuilder.withArgName("host").hasArg().withDescription(
- "use given host for HTTP AUTH").create("host");
- Option username = OptionBuilder.withArgName("username").hasArg().withDescription(
- "use given username for HTTP AUTH").create("username");
- Option passwd = OptionBuilder.withArgName("passwd").hasArg().withDescription(
- "use given password for HTTP AUTH").create("passwd");
- Option main = OptionBuilder.withArgName("main").hasArg().withDescription(
- "the main class to runtime process").create("main");
- Option args = OptionBuilder.withArgName("args").hasArgs().withDescription(
- "the arguments to runtime process").create("args");
- Option cp = OptionBuilder.withArgName("cp").hasArg().withDescription(
- "extra classpath, used only in combination with option main").create("cp");
-
- Options options = new Options();
-
- options.addOption("debug", false, "set message level to debug");
- options.addOption("verbose", false, "set message level to verbose");
- options.addOption("warn", false, "set message level to warn");
- options.addOption("error", false, "set message level to error");
- options.addOption("novalidate", false, "do not validate ivy files against xsd");
- options.addOption("useOrigin", false,
- "DEPRECATED: use original artifact location "
- + "with local resolvers instead of copying to the cache");
- options.addOption("sync", false, "in conjonction with -retrieve, does a synced retrieve");
- options.addOption("m2compatible", false, "use maven2 compatibility");
- options.addOption("?", false, "display this help");
- options.addOption(conf);
- options.addOption(settings);
- options.addOption(confs);
- options.addOption(cache);
- options.addOption(ivyfile);
- options.addOption(dependency);
- options.addOption(retrieve);
- options.addOption(cachepath);
- options.addOption(revision);
- options.addOption(status);
- options.addOption(deliver);
- options.addOption(publishResolver);
- options.addOption(publishPattern);
- options.addOption(realm);
- options.addOption(host);
- options.addOption(username);
- options.addOption(passwd);
- options.addOption(main);
- options.addOption(args);
- options.addOption(cp);
-
- return options;
+ + "of the given ivy file to the given cachepathfile").create())
+
+ .addCategory("deliver options")
+ .addOption(new OptionBuilder("deliverto").arg("ivypattern")
+ .description("use given pattern as resolved ivy file pattern").create())
+
+ .addCategory("publish options")
+ .addOption(new OptionBuilder("publish").arg("resolvername")
+ .description("use given resolver to publish to").create())
+ .addOption(new OptionBuilder("publishpattern").arg("artpattern")
+ .description("use given pattern to find artifacts to publish").create())
+ .addOption(new OptionBuilder("revision").arg("revision")
+ .description("use given revision to publish the module").create())
+ .addOption(new OptionBuilder("status").arg("status")
+ .description("use given status to publish the module").create())
+
+ .addCategory("http auth options")
+ .addOption(new OptionBuilder("realm").arg("realm")
+ .description("use given realm for HTTP AUTH").create())
+ .addOption(new OptionBuilder("host").arg("host")
+ .description("use given host for HTTP AUTH").create())
+ .addOption(new OptionBuilder("username").arg("username")
+ .description("use given username for HTTP AUTH").create())
+ .addOption(new OptionBuilder("passwd").arg("passwd")
+ .description("use given password for HTTP AUTH").create())
+
+ .addCategory("launcher options")
+ .addOption(new OptionBuilder("main").arg("main")
+ .description("the FQCN of the main class to launch").create())
+ .addOption(new OptionBuilder("args").arg("args").countArgs(false)
+ .description("the arguments to give to the launched process").create())
+ .addOption(new OptionBuilder("cp").arg("cp")
+ .description("extra classpath to use when launching process").create())
+
+ .addCategory("message options")
+ .addOption(new OptionBuilder("debug")
+ .description("set message level to debug").create())
+ .addOption(new OptionBuilder("verbose")
+ .description("set message level to verbose").create())
+ .addOption(new OptionBuilder("warn")
+ .description("set message level to warn").create())
+ .addOption(new OptionBuilder("error")
+ .description("set message level to error").create())
+
+ .addCategory("help options")
+ .addOption(new OptionBuilder("?")
+ .description("display this help").create())
+ .addOption(new OptionBuilder("deprecated")
+ .description("show deprecated options").create());
}
public static void main(String[] args) throws Exception {
- Options options = getOptions();
-
- CommandLineParser parser = new GnuParser();
+ CommandLineParser parser = getParser();
try {
+ run(parser, args);
+ } catch (ParseException ex) {
+ System.err.println(ex.getMessage());
+ usage(parser, false);
+ System.exit(1);
+ }
+ }
+
+ static void run(CommandLineParser parser, String[] args) throws Exception {
// parse the command line arguments
- CommandLine line = parser.parse(options, args);
+ CommandLine line = parser.parse(args);
if (line.hasOption("?")) {
- usage(options);
+ usage(parser, line.hasOption("deprecated"));
return;
}
@@ -180,14 +182,14 @@
Ivy ivy = Ivy.newInstance();
initMessage(line, ivy);
- IvySettings settings = initSettings(line, options, ivy);
+ IvySettings settings = initSettings(line, ivy);
File cache = new File(settings.substitute(line.getOptionValue("cache", settings
.getDefaultCache().getAbsolutePath())));
if (!cache.exists()) {
cache.mkdirs();
} else if (!cache.isDirectory()) {
- error(options, cache + " is not a directory");
+ error(cache + " is not a directory");
}
String[] confs;
@@ -200,11 +202,6 @@
File ivyfile;
if (line.hasOption("dependency")) {
String[] dep = line.getOptionValues("dependency");
- if (dep.length != DEPENDENCY_ARG_COUNT) {
- error(options,
- "dependency should be expressed with exactly 3 arguments: "
- + "organisation module revision");
- }
ivyfile = File.createTempFile("ivy", ".xml");
ivyfile.deleteOnExit();
DefaultModuleDescriptor md = DefaultModuleDescriptor
@@ -221,9 +218,9 @@
} else {
ivyfile = new File(settings.substitute(line.getOptionValue("ivy", "ivy.xml")));
if (!ivyfile.exists()) {
- error(options, "ivy file not found: " + ivyfile);
+ error("ivy file not found: " + ivyfile);
} else if (ivyfile.isDirectory()) {
- error(options, "ivy file is not a file: " + ivyfile);
+ error("ivy file is not a file: " + ivyfile);
}
}
@@ -281,7 +278,7 @@
if (fargs == null) {
fargs = new String[0];
}
- String[] extra = line.getArgs();
+ String[] extra = line.getLeftOverArgs();
if (extra == null) {
extra = new String[0];
}
@@ -292,12 +289,6 @@
invoke(ivy, cache, md, confs, fileList, line.getOptionValue("main"), params);
}
ivy.getLoggerEngine().popLogger();
- } catch (ParseException exp) {
- // oops, something went wrong
- System.err.println("Parsing failed. Reason: " + exp.getMessage());
-
- usage(options);
- }
}
/**
@@ -335,8 +326,8 @@
return fileList;
}
- private static IvySettings initSettings(CommandLine line, Options options, Ivy ivy)
- throws java.text.ParseException, IOException {
+ private static IvySettings initSettings(CommandLine line, Ivy ivy)
+ throws java.text.ParseException, IOException, ParseException {
IvySettings settings = ivy.getSettings();
settings.addAllVariables(System.getProperties());
if (line.hasOption("m2compatible")) {
@@ -358,9 +349,9 @@
} else {
File conffile = new File(settingsPath);
if (!conffile.exists()) {
- error(options, "ivy configuration file not found: " + conffile);
+ error("ivy configuration file not found: " + conffile);
} else if (conffile.isDirectory()) {
- error(options, "ivy configuration file is not a file: " + conffile);
+ error("ivy configuration file is not a file: " + conffile);
}
ivy.configure(conffile);
}
@@ -491,16 +482,15 @@
URLHandlerRegistry.setDefault(dispatcher);
}
- private static void error(Options options, String msg) {
- System.err.println(msg);
- usage(options);
- System.exit(1);
+ private static void error(String msg) throws ParseException {
+ throw new ParseException(msg);
}
- private static void usage(Options options) {
+ private static void usage(CommandLineParser parser, boolean showDeprecated) {
// automatically generate the help statement
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("ivy", options);
+ PrintWriter pw = new PrintWriter(System.out);
+ parser.printHelp(pw, HELP_WIDTH, "ivy", showDeprecated);
+ pw.flush();
}
private Main() {
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/StringUtils.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/StringUtils.java?rev=632381&r1=632380&r2=632381&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/StringUtils.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/StringUtils.java Fri Feb 29 08:40:52 2008
@@ -176,4 +176,12 @@
+ "'. Unhandled character.");
}
+ public static String repeat(String str, int count) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < count; i++) {
+ sb.append(str);
+ }
+ return sb.toString();
+ }
+
}
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.util.cli;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CommandLine {
+ private Map/*<String, String[]>*/ optionValues = new HashMap();
+ private String[] leftOverArgs;
+
+ void addOptionValues(String option, String[] values) {
+ optionValues.put(option, values);
+ }
+
+ void setLeftOverArgs(String[] args) {
+ leftOverArgs = args;
+ }
+
+ public boolean hasOption(String option) {
+ return optionValues.containsKey(option);
+ }
+
+ public String getOptionValue(String option) {
+ String[] values = getOptionValues(option);
+ return values == null || values.length == 0 ? null : values[0];
+ }
+
+ public String getOptionValue(String option, String defaultValue) {
+ String value = getOptionValue(option);
+ return value == null ? defaultValue : value;
+ }
+
+ public String[] getOptionValues(String option) {
+ return (String[]) optionValues.get(option);
+ }
+
+ public String[] getLeftOverArgs() {
+ return leftOverArgs;
+ }
+
+}
Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLine.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.util.cli;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.ivy.util.StringUtils;
+
+public class CommandLineParser {
+ private static final int MIN_DESC_WIDTH = 40;
+ private static final int MAX_SPEC_WIDTH = 30;
+ private Map/*<String, Option>*/ options = new LinkedHashMap();
+ private Map/*<String, List<Option>>*/ categories = new LinkedHashMap();
+
+ public CommandLineParser() {
+ }
+
+ public CommandLineParser addCategory(String category) {
+ categories.put(category, new ArrayList());
+ return this;
+ }
+
+ public CommandLineParser addOption(Option option) {
+ options.put(option.getName(), option);
+ if (!categories.isEmpty()) {
+ ((List) categories.values().toArray()[categories.values().size() - 1])
+ .add(option);
+ }
+ return this;
+ }
+
+ public CommandLine parse(String[] args) throws ParseException {
+ CommandLine line = new CommandLine();
+ for (ListIterator iterator = Arrays.asList(args).listIterator(); iterator.hasNext();) {
+ String arg = (String) iterator.next();
+ if (arg.startsWith("-")) {
+ Option option = (Option) options.get(arg.substring(1));
+ if (option == null) {
+ throw new ParseException("Unrecognized option: " + arg);
+ }
+ line.addOptionValues(arg.substring(1), option.parse(iterator));
+ } else {
+ // left over args
+ int index = iterator.previousIndex() + 1;
+ String[] leftOverArgs = new String[args.length - index];
+ System.arraycopy(args, index, leftOverArgs, 0, leftOverArgs.length);
+ line.setLeftOverArgs(leftOverArgs);
+ }
+ }
+ return line;
+ }
+
+ public void printHelp(PrintWriter pw, int width, String command, boolean showDeprecated) {
+ pw.println("usage: " + command);
+ // compute the largest option spec
+ int specWidth = 0;
+ for (Iterator iterator = options.values().iterator(); iterator.hasNext();) {
+ Option option = (Option) iterator.next();
+ if (option.isDeprecated() && !showDeprecated) {
+ continue;
+ }
+ specWidth = Math.min(MAX_SPEC_WIDTH,
+ Math.max(specWidth, option.getSpec().length()));
+ }
+
+ // print options help
+ for (Iterator iterator = categories.entrySet().iterator(); iterator.hasNext();) {
+ Entry entry = (Entry) iterator.next();
+ String category = (String) entry.getKey();
+ pw.println("==== " + category);
+ List/*<Option>*/ options = (List) entry.getValue();
+ for (Iterator it = options.iterator(); it.hasNext();) {
+ Option option = (Option) it.next();
+ if (option.isDeprecated() && !showDeprecated) {
+ continue;
+ }
+ // print option spec: option name + argument names
+ String spec = option.getSpec();
+ pw.print(" " + spec);
+ int specLength = spec.length() + 1;
+ pw.print(StringUtils.repeat(" ", specWidth - specLength));
+
+ // print description
+ StringBuffer desc = new StringBuffer(
+ (option.isDeprecated() ? "DEPRECATED: " : "") + option.getDescription());
+ int count = Math.min(desc.length(), width - Math.max(specLength, specWidth));
+ // see if we have enough space to start on the same line as the spec
+ if (count > MIN_DESC_WIDTH || desc.length() + specLength < width) {
+ pw.print(desc.substring(0, count));
+ desc.delete(0, count);
+ }
+ pw.println();
+
+ // print remaining description
+ while (desc.length() > 0) {
+ pw.print(StringUtils.repeat(" ", specWidth));
+ count = Math.min(desc.length(), width - specWidth);
+ pw.println(desc.substring(0, count));
+ desc.delete(0, count);
+ }
+ }
+ pw.println();
+ }
+ }
+}
Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/CommandLineParser.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.util.cli;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+public class Option {
+ private String name;
+ private String[] args;
+ private String description;
+ private boolean required;
+ private boolean countArgs;
+ private boolean deprecated;
+
+ Option(String name, String[] args, String description,
+ boolean required, boolean countArgs, boolean deprecated) {
+ this.name = name;
+ this.args = args;
+ this.description = description;
+ this.required = required;
+ this.countArgs = countArgs;
+ this.deprecated = deprecated;
+ if (required) {
+ throw new UnsupportedOperationException("required option not supported yet");
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+ public String[] getArgs() {
+ return args;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public boolean isRequired() {
+ return required;
+ }
+ public boolean isCountArgs() {
+ return countArgs;
+ }
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ String[] parse(ListIterator iterator) throws ParseException {
+ if (isCountArgs()) {
+ String[] values = new String[args.length];
+ for (int i = 0; i < values.length; i++) {
+ if (!iterator.hasNext()) {
+ missingArgument(i);
+ }
+ values[i] = (String) iterator.next();
+ if (values[i].startsWith("-")) {
+ missingArgument(i);
+ }
+ }
+ return values;
+ } else {
+ List values = new ArrayList();
+ while (iterator.hasNext()) {
+ String value = (String) iterator.next();
+ if (value.startsWith("-")) {
+ iterator.previous();
+ break;
+ }
+ values.add(value);
+ }
+ return (String[]) values.toArray(new String[values.size()]);
+ }
+ }
+
+ private void missingArgument(int i) throws ParseException {
+ if (i == 0) {
+ throw new ParseException("no argument for: " + name);
+ } else {
+ throw new ParseException("missing argument for: " + name
+ + ". Expected: " + getArgsSpec());
+ }
+ }
+
+ public String getSpec() {
+ return "-" + name + " " + getArgsSpec();
+ }
+
+ private String getArgsSpec() {
+ if (args.length == 0) {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < args.length; i++) {
+ sb.append("<").append(args[i]).append("> ");
+ }
+ return sb.toString();
+ }
+}
Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/Option.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.util.cli;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OptionBuilder {
+ private String name;
+ private List/*<String>*/ args = new ArrayList();
+ private String description = "";
+ private boolean required = false;
+ private boolean countArgs = true;
+ private boolean deprecated = false;
+
+ public OptionBuilder(String name) {
+ this.name = name;
+ }
+
+ public OptionBuilder required(boolean required) {
+ this.required = required;
+ return this;
+ }
+
+ public OptionBuilder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public OptionBuilder arg(String argName) {
+ this.args.add(argName);
+ return this;
+ }
+
+ public OptionBuilder countArgs(boolean countArgs) {
+ this.countArgs = countArgs;
+ return this;
+ }
+
+ public OptionBuilder deprecated() {
+ this.deprecated = true;
+ return this;
+ }
+
+ public Option create() {
+ return new Option(
+ name, (String[]) args.toArray(new String[args.size()]),
+ description, required, countArgs, deprecated);
+ }
+}
Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/OptionBuilder.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.util.cli;
+
+public class ParseException extends Exception {
+ public ParseException(String reason) {
+ super(reason);
+ }
+}
Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/cli/ParseException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java?rev=632381&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java Fri Feb 29 08:40:52 2008
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy;
+
+import java.io.File;
+
+import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.util.CacheCleaner;
+import org.apache.ivy.util.cli.ParseException;
+
+import junit.framework.TestCase;
+
+public class MainTest extends TestCase {
+
+ private File cache;
+
+ protected void setUp() throws Exception {
+ cache = new File("build/cache");
+ System.setProperty("ivy.cache.dir", cache.getAbsolutePath());
+ }
+
+ protected void tearDown() throws Exception {
+ CacheCleaner.deleteDir(cache);
+ }
+
+ public void testHelp() throws Exception {
+ run(new String[] {"-?"});
+ }
+
+ public void testBadOption() throws Exception {
+ try {
+ run(new String[] {"-bad"});
+ fail("running Ivy Main with -bad option should raise an exception");
+ } catch (ParseException ex) {
+ assertEquals("Unrecognized option: -bad", ex.getMessage());
+ }
+ }
+
+ public void testMissingParameter() throws Exception {
+ try {
+ run(new String[] {"-ivy"});
+ fail("running Ivy Main with missing argument for -ivy option should raise an exception");
+ } catch (ParseException ex) {
+ assertEquals("no argument for: ivy", ex.getMessage());
+ }
+ }
+
+ public void testResolveSimple() throws Exception {
+ run(new String[] {
+ "-settings", "test/repositories/ivysettings.xml",
+ "-ivy", "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"
+ });
+ assertTrue(new File("build/cache/org1/mod1.2/ivy-2.0.xml").exists());
+ }
+
+ public void testResolveSimpleWithConfs() throws Exception {
+ run(new String[] {
+ "-settings", "test/repositories/ivysettings.xml",
+ "-ivy", "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml",
+ "-confs", "default"
+ });
+ assertTrue(new File("build/cache/org1/mod1.2/ivy-2.0.xml").exists());
+ }
+
+ public void testResolveSimpleWithConfs2() throws Exception {
+ run(new String[] {
+ "-settings", "test/repositories/ivysettings.xml",
+ "-confs", "default",
+ "-ivy", "test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml"
+ });
+ assertTrue(new File("build/cache/org1/mod1.2/ivy-2.0.xml").exists());
+ }
+
+ private void run(String[] args) throws Exception {
+ Main.run(Main.getParser(), args);
+ }
+}
Propchange: ant/ivy/core/trunk/test/java/org/apache/ivy/MainTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain