1 6 package fr.jayasoft.ivy; 7 8 import java.io.File ; 9 import java.io.FileOutputStream ; 10 import java.io.PrintWriter ; 11 import java.lang.reflect.InvocationTargetException ; 12 import java.lang.reflect.Method ; 13 import java.net.URL ; 14 import java.net.URLClassLoader ; 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.Collection ; 18 import java.util.Date ; 19 import java.util.Iterator ; 20 import java.util.LinkedHashSet ; 21 import java.util.List ; 22 23 import org.apache.commons.cli.CommandLine; 24 import org.apache.commons.cli.CommandLineParser; 25 import org.apache.commons.cli.GnuParser; 26 import org.apache.commons.cli.HelpFormatter; 27 import org.apache.commons.cli.Option; 28 import org.apache.commons.cli.OptionBuilder; 29 import org.apache.commons.cli.Options; 30 import org.apache.commons.cli.ParseException; 31 import org.apache.tools.ant.BuildException; 32 import org.apache.tools.ant.types.Path; 33 34 import fr.jayasoft.ivy.report.ResolveReport; 35 import fr.jayasoft.ivy.url.CredentialsStore; 36 import fr.jayasoft.ivy.url.URLHandler; 37 import fr.jayasoft.ivy.url.URLHandlerDispatcher; 38 import fr.jayasoft.ivy.url.URLHandlerRegistry; 39 import fr.jayasoft.ivy.util.DefaultMessageImpl; 40 import fr.jayasoft.ivy.util.Message; 41 import fr.jayasoft.ivy.xml.XmlModuleDescriptorWriter; 42 import fr.jayasoft.ivy.xml.XmlReportParser; 43 44 60 public class Main { 61 private static Options getOptions() { 62 Option conf = OptionBuilder.withArgName( "conffile" ) 63 .hasArg() 64 .withDescription( "use given file for configuration" ) 65 .create( "conf" ); 66 Option cache = OptionBuilder.withArgName( "cachedir" ) 67 .hasArg() 68 .withDescription( "use given directory for cache" ) 69 .create( "cache" ); 70 Option ivyfile = OptionBuilder.withArgName( "ivyfile" ) 71 .hasArg() 72 .withDescription( "use given file as ivy file" ) 73 .create( "ivy" ); 74 Option dependency = OptionBuilder.withArgName( "organisation module revision" ) 75 .hasArgs() 76 .withDescription( "use this instead of ivy file to do the rest of the work with this as a dependency." ) 77 .create( "dependency" ); 78 Option confs = OptionBuilder.withArgName( "configurations" ) 79 .hasArgs() 80 .withDescription( "resolve given configurations" ) 81 .create( "confs" ); 82 Option retrieve = OptionBuilder.withArgName( "retrievepattern" ) 83 .hasArg() 84 .withDescription( "use given pattern as retrieve pattern" ) 85 .create( "retrieve" ); 86 Option cachepath = OptionBuilder.withArgName( "cachepathfile" ) 87 .hasArg() 88 .withDescription( "outputs a classpath consisting of all dependencies in cache (including transitive ones) of the given ivy file to the given cachepathfile" ) 89 .create( "cachepath" ); 90 Option revision = OptionBuilder.withArgName( "revision" ) 91 .hasArg() 92 .withDescription( "use given revision to publish the module" ) 93 .create( "revision" ); 94 Option status = OptionBuilder.withArgName( "status" ) 95 .hasArg() 96 .withDescription( "use given status to publish the module" ) 97 .create( "status" ); 98 Option deliver = OptionBuilder.withArgName( "ivypattern" ) 99 .hasArg() 100 .withDescription( "use given pattern as resolved ivy file pattern" ) 101 .create( "deliverto" ); 102 Option publishResolver = OptionBuilder.withArgName( "resolvername" ) 103 .hasArg() 104 .withDescription( "use given resolver to publish to" ) 105 .create( "publish" ); 106 Option publishPattern = OptionBuilder.withArgName( "artpattern" ) 107 .hasArg() 108 .withDescription( "use given pattern to find artifacts to publish" ) 109 .create( "publishpattern" ); 110 Option realm = OptionBuilder.withArgName( "realm" ) 111 .hasArg() 112 .withDescription( "use given realm for HTTP AUTH" ) 113 .create( "realm" ); 114 Option host = OptionBuilder.withArgName( "host" ) 115 .hasArg() 116 .withDescription( "use given host for HTTP AUTH" ) 117 .create( "host" ); 118 Option username = OptionBuilder.withArgName( "username" ) 119 .hasArg() 120 .withDescription( "use given username for HTTP AUTH" ) 121 .create( "username" ); 122 Option passwd = OptionBuilder.withArgName( "passwd" ) 123 .hasArg() 124 .withDescription( "use given password for HTTP AUTH" ) 125 .create( "passwd" ); 126 Option main = OptionBuilder.withArgName("main") 127 .hasArg() 128 .withDescription("the main class to runtime process") 129 .create("main"); 130 Option args = OptionBuilder.withArgName("args") 131 .hasArgs() 132 .withDescription("the arguments to runtime process") 133 .create("args"); 134 135 Options options = new Options(); 136 137 options.addOption("debug", false, "set message level to debug"); 138 options.addOption("verbose", false, "set message level to verbose"); 139 options.addOption("warn", false, "set message level to warn"); 140 options.addOption("error", false, "set message level to error"); 141 options.addOption("novalidate", false, "do not validate ivy files against xsd"); 142 options.addOption("useOrigin", false, "use original artifact location with local resolvers instead of copying to the cache"); 143 options.addOption("sync", false, "in conjonction with -retrieve, does a synced retrieve"); 144 options.addOption("m2compatible", false, "use maven2 compatibility"); 145 options.addOption("?", false, "display this help"); 146 options.addOption(conf); 147 options.addOption(confs); 148 options.addOption(cache); 149 options.addOption(ivyfile); 150 options.addOption(dependency); 151 options.addOption(retrieve); 152 options.addOption(cachepath); 153 options.addOption(revision); 154 options.addOption(status); 155 options.addOption(deliver); 156 options.addOption(publishResolver); 157 options.addOption(publishPattern); 158 options.addOption(realm); 159 options.addOption(host); 160 options.addOption(username); 161 options.addOption(passwd); 162 options.addOption(main); 163 options.addOption(args); 164 165 return options; 166 } 167 public static void main(String [] args) throws Exception { 168 Options options = getOptions(); 169 170 CommandLineParser parser = new GnuParser(); 171 try { 172 CommandLine line = parser.parse( options, args ); 174 175 if (line.hasOption("?")) { 176 usage(options); 177 return; 178 } 179 180 if (line.hasOption("debug")) { 181 Message.init(new DefaultMessageImpl(Message.MSG_DEBUG)); 182 } else if (line.hasOption("verbose")) { 183 Message.init(new DefaultMessageImpl(Message.MSG_VERBOSE)); 184 } else if (line.hasOption("warn")) { 185 Message.init(new DefaultMessageImpl(Message.MSG_WARN)); 186 } else if (line.hasOption("error")) { 187 Message.init(new DefaultMessageImpl(Message.MSG_ERR)); 188 } else { 189 Message.init(new DefaultMessageImpl(Message.MSG_INFO)); 190 } 191 192 boolean validate = line.hasOption("novalidate")?false:true; 193 194 Ivy ivy = new Ivy(); 195 ivy.addAllVariables(System.getProperties()); 196 if (line.hasOption("m2compatible")) { 197 ivy.setVariable("ivy.default.configuration.m2compatible", "true"); 198 } 199 200 configureURLHandler( 201 line.getOptionValue("realm", null), 202 line.getOptionValue("host", null), 203 line.getOptionValue("username", null), 204 line.getOptionValue("passwd", null)); 205 206 String confPath = line.getOptionValue("conf", ""); 207 if ("".equals(confPath)) { 208 ivy.configureDefault(); 209 } else { 210 File conffile = new File (confPath); 211 if (!conffile.exists()) { 212 error(options, "ivy configuration file not found: "+conffile); 213 } else if (conffile.isDirectory()) { 214 error(options, "ivy configuration file is not a file: "+conffile); 215 } 216 ivy.configure(conffile); 217 } 218 219 File cache = new File (ivy.substitute(line.getOptionValue("cache", ivy.getDefaultCache().getAbsolutePath()))); 220 if (!cache.exists()) { 221 cache.mkdirs(); 222 } else if (!cache.isDirectory()) { 223 error(options, cache+" is not a directory"); 224 } 225 226 String [] confs; 227 if (line.hasOption("confs")) { 228 confs = line.getOptionValues("confs"); 229 } else { 230 confs = new String [] {"*"}; 231 } 232 233 File ivyfile; 234 if (line.hasOption("dependency")) { 235 String [] dep = line.getOptionValues("dependency"); 236 if (dep.length != 3) { 237 error(options, "dependency should be expressed with exactly 3 arguments: organisation module revision"); 238 } 239 ivyfile = File.createTempFile("ivy", ".xml"); 240 ivyfile.deleteOnExit(); 241 DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(ModuleRevisionId.newInstance(dep[0], dep[1]+"-caller", "working")); 242 DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, ModuleRevisionId.newInstance(dep[0], dep[1], dep[2]), false, false, true); 243 for (int i = 0; i < confs.length; i++) { 244 dd.addDependencyConfiguration("default", confs[i]); 245 } 246 md.addDependency(dd); 247 XmlModuleDescriptorWriter.write(md, ivyfile); 248 confs = new String [] {"default"}; 249 } else { 250 ivyfile = new File (ivy.substitute(line.getOptionValue("ivy", "ivy.xml"))); 251 if (!ivyfile.exists()) { 252 error(options, "ivy file not found: "+ivyfile); 253 } else if (ivyfile.isDirectory()) { 254 error(options, "ivy file is not a file: "+ivyfile); 255 } 256 } 257 258 259 ResolveReport report = ivy.resolve( 260 ivyfile.toURL(), 261 null, 262 confs, 263 cache, 264 null, 265 validate, 266 false, 267 true, 268 line.hasOption("useOrigin"), 269 null 270 ); 271 if (report.hasError()) { 272 System.exit(1); 273 } 274 ModuleDescriptor md = report.getModuleDescriptor(); 275 276 if (confs.length == 1 && "*".equals(confs[0])) { 277 confs = md.getConfigurationsNames(); 278 } 279 if (line.hasOption("retrieve")) { 280 String retrievePattern = ivy.substitute(line.getOptionValue("retrieve")); 281 if (retrievePattern.indexOf("[") == -1) { 282 retrievePattern = retrievePattern + "/lib/[conf]/[artifact].[ext]"; 283 } 284 ivy.retrieve(md.getModuleRevisionId().getModuleId(), confs, cache, retrievePattern, null, null, line.hasOption("sync"), line.hasOption("useOrigin")); 285 } 286 if (line.hasOption("cachepath")) { 287 outputCachePath(ivy, cache, md, confs, line.getOptionValue("cachepath", "ivycachepath.txt")); 288 } 289 290 if (line.hasOption("revision")) { 291 ivy.deliver( 292 md.getResolvedModuleRevisionId(), 293 ivy.substitute(line.getOptionValue("revision")), 294 cache, 295 ivy.substitute(line.getOptionValue("deliverto", "ivy-[revision].xml")), 296 ivy.substitute(line.getOptionValue("status", "release")), 297 null, 298 new DefaultPublishingDRResolver(), 299 validate); 300 if (line.hasOption("publish")) { 301 ivy.publish( 302 md.getResolvedModuleRevisionId(), 303 ivy.substitute(line.getOptionValue("revision")), 304 cache, 305 ivy.substitute(line.getOptionValue("publishpattern", "distrib/[type]s/[artifact]-[revision].[ext]")), 306 line.getOptionValue("publish"), 307 ivy.substitute(line.getOptionValue("deliverto", "ivy-[revision].xml")), 308 validate); 309 310 } 311 } 312 if (line.hasOption("main")) { 313 invoke(ivy, cache, md, confs, line.getOptionValue("main"), 314 line.getOptionValues("args")); 315 } 316 } catch( ParseException exp ) { 317 System.err.println( "Parsing failed. Reason: " + exp.getMessage() ); 319 320 usage(options); 321 } 322 } 323 324 private static void outputCachePath(Ivy ivy, File cache, ModuleDescriptor md, String [] confs, String outFile) { 325 try { 326 String pathSeparator = System.getProperty("path.separator"); 327 StringBuffer buf = new StringBuffer (); 328 XmlReportParser parser = new XmlReportParser(); 329 Collection all = new LinkedHashSet (); 330 for (int i = 0; i < confs.length; i++) { 331 Artifact[] artifacts = parser.getArtifacts(md.getModuleRevisionId().getModuleId(), confs[i], cache); 332 all.addAll(Arrays.asList(artifacts)); 333 } 334 for (Iterator iter = all.iterator(); iter.hasNext();) { 335 Artifact artifact = (Artifact)iter.next(); 336 buf.append(ivy.getArchiveFileInCache(cache, artifact).getCanonicalPath()); 337 if (iter.hasNext()) { 338 buf.append(pathSeparator); 339 } 340 } 341 PrintWriter writer = new PrintWriter (new FileOutputStream (outFile)); 342 writer.println(buf.toString()); 343 writer.close(); 344 System.out.println("cachepath output to "+outFile); 345 346 } catch (Exception ex) { 347 throw new RuntimeException ("impossible to build ivy cache path: "+ex.getMessage(), ex); 348 } 349 } 350 351 private static void invoke(Ivy ivy, File cache, ModuleDescriptor md, String [] confs, String mainclass, String [] args) { 352 List urls = new ArrayList (); 353 354 try { 355 XmlReportParser parser = new XmlReportParser(); 356 Collection all = new LinkedHashSet (); 357 for (int i = 0; i < confs.length; i++) { 358 Artifact[] artifacts = parser.getArtifacts(md.getModuleRevisionId().getModuleId(), confs[i], cache); 359 all.addAll(Arrays.asList(artifacts)); 360 } 361 for (Iterator iter = all.iterator(); iter.hasNext();) { 362 Artifact artifact = (Artifact)iter.next(); 363 364 urls.add(ivy.getArchiveFileInCache(cache, artifact).toURL()); 365 } 366 } catch (Exception ex) { 367 throw new RuntimeException ("impossible to build ivy cache path: "+ex.getMessage(), ex); 368 } 369 370 URLClassLoader classLoader = new URLClassLoader ( 371 (URL []) urls.toArray(new URL [urls.size()]), 372 Main.class.getClassLoader()); 373 374 try { 375 Class c = classLoader.loadClass(mainclass); 376 377 Method mainMethod = c.getMethod("main", new Class [] { String [].class }); 378 379 mainMethod.invoke(null, new Object [] { args }); 381 } catch (ClassNotFoundException cnfe) { 382 throw new RuntimeException ("Could not find class: " + mainclass, cnfe); 383 } catch (SecurityException e) { 384 throw new RuntimeException ("Could not find main method: " + mainclass, e); 385 } catch (NoSuchMethodException e) { 386 throw new RuntimeException ("Could not find main method: " + mainclass, e); 387 } catch (IllegalAccessException e) { 388 throw new RuntimeException ("No permissions to invoke main method: " + mainclass, e); 389 } catch (InvocationTargetException e) { 390 throw new RuntimeException ("Unexpected exception invoking main method: " + mainclass, e); 391 } 392 } 393 private static void configureURLHandler(String realm, String host, String username, String passwd) { 394 CredentialsStore.INSTANCE.addCredentials(realm, host, username, passwd); 395 396 URLHandlerDispatcher dispatcher = new URLHandlerDispatcher(); 397 URLHandler httpHandler = URLHandlerRegistry.getHttp(); 398 dispatcher.setDownloader("http", httpHandler); 399 dispatcher.setDownloader("https", httpHandler); 400 URLHandlerRegistry.setDefault(dispatcher); 401 } 402 403 private static void error(Options options, String msg) { 404 System.err.println(msg); 405 usage(options); 406 System.exit(1); 407 } 408 409 private static void usage(Options options) { 410 HelpFormatter formatter = new HelpFormatter(); 412 formatter.printHelp( "ivy", options ); 413 } 414 415 } 416 | Popular Tags |