src/share/jaxws_classes/com/sun/tools/internal/xjc/Driver.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.internal.xjc;
aoqi@0 27
aoqi@0 28 import java.io.File;
aoqi@0 29 import java.io.FileOutputStream;
aoqi@0 30 import java.io.IOException;
aoqi@0 31 import java.io.OutputStream;
aoqi@0 32 import java.io.OutputStreamWriter;
aoqi@0 33 import java.io.PrintStream;
aoqi@0 34 import java.util.Iterator;
aoqi@0 35
aoqi@0 36 import com.sun.codemodel.internal.CodeWriter;
aoqi@0 37 import com.sun.codemodel.internal.JCodeModel;
aoqi@0 38 import com.sun.codemodel.internal.writer.ZipCodeWriter;
aoqi@0 39 import com.sun.istack.internal.NotNull;
aoqi@0 40 import com.sun.istack.internal.Nullable;
aoqi@0 41 import com.sun.istack.internal.tools.DefaultAuthenticator;
aoqi@0 42 import com.sun.tools.internal.xjc.generator.bean.BeanGenerator;
aoqi@0 43 import com.sun.tools.internal.xjc.model.Model;
aoqi@0 44 import com.sun.tools.internal.xjc.outline.Outline;
aoqi@0 45 import com.sun.tools.internal.xjc.reader.gbind.Expression;
aoqi@0 46 import com.sun.tools.internal.xjc.reader.gbind.Graph;
aoqi@0 47 import com.sun.tools.internal.xjc.reader.internalizer.DOMForest;
aoqi@0 48 import com.sun.tools.internal.xjc.reader.xmlschema.ExpressionBuilder;
aoqi@0 49 import com.sun.tools.internal.xjc.reader.xmlschema.parser.XMLSchemaInternalizationLogic;
aoqi@0 50 import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
aoqi@0 51 import com.sun.tools.internal.xjc.util.NullStream;
aoqi@0 52 import com.sun.tools.internal.xjc.util.Util;
aoqi@0 53 import com.sun.tools.internal.xjc.writer.SignatureWriter;
aoqi@0 54 import com.sun.xml.internal.xsom.XSComplexType;
aoqi@0 55 import com.sun.xml.internal.xsom.XSParticle;
aoqi@0 56 import com.sun.xml.internal.xsom.XSSchemaSet;
aoqi@0 57
aoqi@0 58 import org.xml.sax.SAXException;
aoqi@0 59 import org.xml.sax.SAXParseException;
aoqi@0 60
aoqi@0 61
aoqi@0 62 /**
aoqi@0 63 * Command Line Interface of XJC.
aoqi@0 64 */
aoqi@0 65 public class Driver {
aoqi@0 66
aoqi@0 67 public static void main(final String[] args) throws Exception {
aoqi@0 68 // use the platform default proxy if available.
aoqi@0 69 // see sun.net.spi.DefaultProxySelector for details.
aoqi@0 70 try {
aoqi@0 71 System.setProperty("java.net.useSystemProxies","true");
aoqi@0 72 } catch (SecurityException e) {
aoqi@0 73 // failing to set this property isn't fatal
aoqi@0 74 }
aoqi@0 75
aoqi@0 76 if( Util.getSystemProperty(Driver.class,"noThreadSwap")!=null )
aoqi@0 77 _main(args); // for the ease of debugging
aoqi@0 78
aoqi@0 79 // run all the work in another thread so that the -Xss option
aoqi@0 80 // will take effect when compiling a large schema. See
aoqi@0 81 // http://developer.java.sun.com/developer/bugParade/bugs/4362291.html
aoqi@0 82 final Throwable[] ex = new Throwable[1];
aoqi@0 83
aoqi@0 84 Thread th = new Thread() {
aoqi@0 85 @Override
aoqi@0 86 public void run() {
aoqi@0 87 try {
aoqi@0 88 _main(args);
aoqi@0 89 } catch( Throwable e ) {
aoqi@0 90 ex[0]=e;
aoqi@0 91 }
aoqi@0 92 }
aoqi@0 93 };
aoqi@0 94 th.start();
aoqi@0 95 th.join();
aoqi@0 96
aoqi@0 97 if(ex[0]!=null) {
aoqi@0 98 // re-throw
aoqi@0 99 if( ex[0] instanceof Exception )
aoqi@0 100 throw (Exception)ex[0];
aoqi@0 101 else
aoqi@0 102 throw (Error)ex[0];
aoqi@0 103 }
aoqi@0 104 }
aoqi@0 105
aoqi@0 106 private static void _main( String[] args ) throws Exception {
aoqi@0 107 try {
aoqi@0 108 System.exit(run( args, System.out, System.out ));
aoqi@0 109 } catch (BadCommandLineException e) {
aoqi@0 110 // there was an error in the command line.
aoqi@0 111 // print usage and abort.
aoqi@0 112 if(e.getMessage()!=null) {
aoqi@0 113 System.out.println(e.getMessage());
aoqi@0 114 System.out.println();
aoqi@0 115 }
aoqi@0 116
aoqi@0 117 usage(e.getOptions(),false);
aoqi@0 118 System.exit(-1);
aoqi@0 119 }
aoqi@0 120 }
aoqi@0 121
aoqi@0 122
aoqi@0 123
aoqi@0 124 /**
aoqi@0 125 * Performs schema compilation and prints the status/error into the
aoqi@0 126 * specified PrintStream.
aoqi@0 127 *
aoqi@0 128 * <p>
aoqi@0 129 * This method could be used to trigger XJC from other tools,
aoqi@0 130 * such as Ant or IDE.
aoqi@0 131 *
aoqi@0 132 * @param args
aoqi@0 133 * specified command line parameters. If there is an error
aoqi@0 134 * in the parameters, {@link BadCommandLineException} will
aoqi@0 135 * be thrown.
aoqi@0 136 * @param status
aoqi@0 137 * Status report of the compilation will be sent to this object.
aoqi@0 138 * Useful to update users so that they will know something is happening.
aoqi@0 139 * Only ignorable messages should be sent to this stream.
aoqi@0 140 *
aoqi@0 141 * This parameter can be null to suppress messages.
aoqi@0 142 *
aoqi@0 143 * @param out
aoqi@0 144 * Various non-ignorable output (error messages, etc)
aoqi@0 145 * will go to this stream.
aoqi@0 146 *
aoqi@0 147 * @return
aoqi@0 148 * If the compiler runs successfully, this method returns 0.
aoqi@0 149 * All non-zero values indicate an error. The error message
aoqi@0 150 * will be sent to the specified PrintStream.
aoqi@0 151 */
aoqi@0 152 public static int run(String[] args, final PrintStream status, final PrintStream out)
aoqi@0 153 throws Exception {
aoqi@0 154
aoqi@0 155 class Listener extends XJCListener {
aoqi@0 156 ConsoleErrorReporter cer = new ConsoleErrorReporter(out==null?new PrintStream(new NullStream()):out);
aoqi@0 157
aoqi@0 158 @Override
aoqi@0 159 public void generatedFile(String fileName, int count, int total) {
aoqi@0 160 message(fileName);
aoqi@0 161 }
aoqi@0 162 @Override
aoqi@0 163 public void message(String msg) {
aoqi@0 164 if(status!=null)
aoqi@0 165 status.println(msg);
aoqi@0 166 }
aoqi@0 167
aoqi@0 168 public void error(SAXParseException exception) {
aoqi@0 169 cer.error(exception);
aoqi@0 170 }
aoqi@0 171
aoqi@0 172 public void fatalError(SAXParseException exception) {
aoqi@0 173 cer.fatalError(exception);
aoqi@0 174 }
aoqi@0 175
aoqi@0 176 public void warning(SAXParseException exception) {
aoqi@0 177 cer.warning(exception);
aoqi@0 178 }
aoqi@0 179
aoqi@0 180 public void info(SAXParseException exception) {
aoqi@0 181 cer.info(exception);
aoqi@0 182 }
aoqi@0 183 }
aoqi@0 184
aoqi@0 185 return run(args,new Listener());
aoqi@0 186 }
aoqi@0 187
aoqi@0 188 /**
aoqi@0 189 * Performs schema compilation and prints the status/error into the
aoqi@0 190 * specified PrintStream.
aoqi@0 191 *
aoqi@0 192 * <p>
aoqi@0 193 * This method could be used to trigger XJC from other tools,
aoqi@0 194 * such as Ant or IDE.
aoqi@0 195 *
aoqi@0 196 * @param args
aoqi@0 197 * specified command line parameters. If there is an error
aoqi@0 198 * in the parameters, {@link BadCommandLineException} will
aoqi@0 199 * be thrown.
aoqi@0 200 * @param listener
aoqi@0 201 * Receives messages from XJC reporting progress/errors.
aoqi@0 202 *
aoqi@0 203 * @return
aoqi@0 204 * If the compiler runs successfully, this method returns 0.
aoqi@0 205 * All non-zero values indicate an error. The error message
aoqi@0 206 * will be sent to the specified PrintStream.
aoqi@0 207 */
aoqi@0 208 public static int run(String[] args, @NotNull final XJCListener listener) throws BadCommandLineException {
aoqi@0 209
aoqi@0 210 // recognize those special options before we start parsing options.
aoqi@0 211 for (String arg : args) {
aoqi@0 212 if (arg.equals("-version")) {
aoqi@0 213 listener.message(Messages.format(Messages.VERSION));
aoqi@0 214 return -1;
aoqi@0 215 }
aoqi@0 216 if (arg.equals("-fullversion")) {
aoqi@0 217 listener.message(Messages.format(Messages.FULLVERSION));
aoqi@0 218 return -1;
aoqi@0 219 }
aoqi@0 220 }
aoqi@0 221
aoqi@0 222 final OptionsEx opt = new OptionsEx();
aoqi@0 223 opt.setSchemaLanguage(Language.XMLSCHEMA); // disable auto-guessing
aoqi@0 224 try {
aoqi@0 225 opt.parseArguments(args);
aoqi@0 226 } catch (WeAreDone e) {
aoqi@0 227 if (opt.proxyAuth != null) {
aoqi@0 228 DefaultAuthenticator.reset();
aoqi@0 229 }
aoqi@0 230 return -1;
aoqi@0 231 } catch(BadCommandLineException e) {
aoqi@0 232 if (opt.proxyAuth != null) {
aoqi@0 233 DefaultAuthenticator.reset();
aoqi@0 234 }
aoqi@0 235 e.initOptions(opt);
aoqi@0 236 throw e;
aoqi@0 237 }
aoqi@0 238
aoqi@0 239 // display a warning if the user specified the default package
aoqi@0 240 // this should work, but is generally a bad idea
aoqi@0 241 if(opt.defaultPackage != null && opt.defaultPackage.length()==0) {
aoqi@0 242 listener.message(Messages.format(Messages.WARNING_MSG, Messages.format(Messages.DEFAULT_PACKAGE_WARNING)));
aoqi@0 243 }
aoqi@0 244
aoqi@0 245
aoqi@0 246 // set up the context class loader so that the user-specified classes
aoqi@0 247 // can be loaded from there
aoqi@0 248 final ClassLoader contextClassLoader = SecureLoader.getContextClassLoader();
aoqi@0 249 SecureLoader.setContextClassLoader(opt.getUserClassLoader(contextClassLoader));
aoqi@0 250
aoqi@0 251 // parse a grammar file
aoqi@0 252 //-----------------------------------------
aoqi@0 253 try {
aoqi@0 254 if( !opt.quiet ) {
aoqi@0 255 listener.message(Messages.format(Messages.PARSING_SCHEMA));
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 final boolean[] hadWarning = new boolean[1];
aoqi@0 259
aoqi@0 260 ErrorReceiver receiver = new ErrorReceiverFilter(listener) {
aoqi@0 261 @Override
aoqi@0 262 public void info(SAXParseException exception) {
aoqi@0 263 if(opt.verbose)
aoqi@0 264 super.info(exception);
aoqi@0 265 }
aoqi@0 266 @Override
aoqi@0 267 public void warning(SAXParseException exception) {
aoqi@0 268 hadWarning[0] = true;
aoqi@0 269 if(!opt.quiet)
aoqi@0 270 super.warning(exception);
aoqi@0 271 }
aoqi@0 272 @Override
aoqi@0 273 public void pollAbort() throws AbortException {
aoqi@0 274 if(listener.isCanceled())
aoqi@0 275 throw new AbortException();
aoqi@0 276 }
aoqi@0 277 };
aoqi@0 278
aoqi@0 279 if( opt.mode==Mode.FOREST ) {
aoqi@0 280 // dump DOM forest and quit
aoqi@0 281 ModelLoader loader = new ModelLoader( opt, new JCodeModel(), receiver );
aoqi@0 282 try {
aoqi@0 283 DOMForest forest = loader.buildDOMForest(new XMLSchemaInternalizationLogic());
aoqi@0 284 forest.dump(System.out);
aoqi@0 285 return 0;
aoqi@0 286 } catch (SAXException e) {
aoqi@0 287 // the error should have already been reported
aoqi@0 288 } catch (IOException e) {
aoqi@0 289 receiver.error(e);
aoqi@0 290 }
aoqi@0 291
aoqi@0 292 return -1;
aoqi@0 293 }
aoqi@0 294
aoqi@0 295 if( opt.mode==Mode.GBIND ) {
aoqi@0 296 try {
aoqi@0 297 XSSchemaSet xss = new ModelLoader(opt, new JCodeModel(), receiver).loadXMLSchema();
aoqi@0 298 Iterator<XSComplexType> it = xss.iterateComplexTypes();
aoqi@0 299 while (it.hasNext()) {
aoqi@0 300 XSComplexType ct = it.next();
aoqi@0 301 XSParticle p = ct.getContentType().asParticle();
aoqi@0 302 if(p==null) continue;
aoqi@0 303
aoqi@0 304 Expression tree = ExpressionBuilder.createTree(p);
aoqi@0 305 System.out.println("Graph for "+ct.getName());
aoqi@0 306 System.out.println(tree.toString());
aoqi@0 307 Graph g = new Graph(tree);
aoqi@0 308 System.out.println(g.toString());
aoqi@0 309 System.out.println();
aoqi@0 310 }
aoqi@0 311 return 0;
aoqi@0 312 } catch (SAXException e) {
aoqi@0 313 // the error should have already been reported
aoqi@0 314 }
aoqi@0 315 return -1;
aoqi@0 316 }
aoqi@0 317
aoqi@0 318 Model model = ModelLoader.load( opt, new JCodeModel(), receiver );
aoqi@0 319
aoqi@0 320 if (model == null) {
aoqi@0 321 listener.message(Messages.format(Messages.PARSE_FAILED));
aoqi@0 322 return -1;
aoqi@0 323 }
aoqi@0 324
aoqi@0 325 if( !opt.quiet ) {
aoqi@0 326 listener.message(Messages.format(Messages.COMPILING_SCHEMA));
aoqi@0 327 }
aoqi@0 328
aoqi@0 329 switch (opt.mode) {
aoqi@0 330 case SIGNATURE :
aoqi@0 331 try {
aoqi@0 332 SignatureWriter.write(
aoqi@0 333 BeanGenerator.generate(model,receiver),
aoqi@0 334 new OutputStreamWriter(System.out));
aoqi@0 335 return 0;
aoqi@0 336 } catch (IOException e) {
aoqi@0 337 receiver.error(e);
aoqi@0 338 return -1;
aoqi@0 339 }
aoqi@0 340
aoqi@0 341 case CODE :
aoqi@0 342 case DRYRUN :
aoqi@0 343 case ZIP :
aoqi@0 344 {
aoqi@0 345 // generate actual code
aoqi@0 346 receiver.debug("generating code");
aoqi@0 347 {// don't want to hold outline in memory for too long.
aoqi@0 348 Outline outline = model.generateCode(opt,receiver);
aoqi@0 349 if(outline==null) {
aoqi@0 350 listener.message(
aoqi@0 351 Messages.format(Messages.FAILED_TO_GENERATE_CODE));
aoqi@0 352 return -1;
aoqi@0 353 }
aoqi@0 354
aoqi@0 355 listener.compiled(outline);
aoqi@0 356 }
aoqi@0 357
aoqi@0 358 if( opt.mode == Mode.DRYRUN )
aoqi@0 359 break; // enough
aoqi@0 360
aoqi@0 361 // then print them out
aoqi@0 362 try {
aoqi@0 363 CodeWriter cw;
aoqi@0 364 if( opt.mode==Mode.ZIP ) {
aoqi@0 365 OutputStream os;
aoqi@0 366 if(opt.targetDir.getPath().equals("."))
aoqi@0 367 os = System.out;
aoqi@0 368 else
aoqi@0 369 os = new FileOutputStream(opt.targetDir);
aoqi@0 370
aoqi@0 371 cw = opt.createCodeWriter(new ZipCodeWriter(os));
aoqi@0 372 } else
aoqi@0 373 cw = opt.createCodeWriter();
aoqi@0 374
aoqi@0 375 if( !opt.quiet ) {
aoqi@0 376 cw = new ProgressCodeWriter(cw,listener, model.codeModel.countArtifacts());
aoqi@0 377 }
aoqi@0 378 model.codeModel.build(cw);
aoqi@0 379 } catch (IOException e) {
aoqi@0 380 receiver.error(e);
aoqi@0 381 return -1;
aoqi@0 382 }
aoqi@0 383
aoqi@0 384 break;
aoqi@0 385 }
aoqi@0 386 default :
aoqi@0 387 assert false;
aoqi@0 388 }
aoqi@0 389
aoqi@0 390 if(opt.debugMode) {
aoqi@0 391 try {
aoqi@0 392 new FileOutputStream(new File(opt.targetDir,hadWarning[0]?"hadWarning":"noWarning")).close();
aoqi@0 393 } catch (IOException e) {
aoqi@0 394 receiver.error(e);
aoqi@0 395 return -1;
aoqi@0 396 }
aoqi@0 397 }
aoqi@0 398
aoqi@0 399 return 0;
aoqi@0 400 } catch( StackOverflowError e ) {
aoqi@0 401 if(opt.verbose)
aoqi@0 402 // in the debug mode, propagate the error so that
aoqi@0 403 // the full stack trace will be dumped to the screen.
aoqi@0 404 throw e;
aoqi@0 405 else {
aoqi@0 406 // otherwise just print a suggested workaround and
aoqi@0 407 // quit without filling the user's screen
aoqi@0 408 listener.message(Messages.format(Messages.STACK_OVERFLOW));
aoqi@0 409 return -1;
aoqi@0 410 }
aoqi@0 411 } finally {
aoqi@0 412 if (opt.proxyAuth != null) {
aoqi@0 413 DefaultAuthenticator.reset();
aoqi@0 414 }
aoqi@0 415 }
aoqi@0 416 }
aoqi@0 417
aoqi@0 418 public static String getBuildID() {
aoqi@0 419 return Messages.format(Messages.BUILD_ID);
aoqi@0 420 }
aoqi@0 421
aoqi@0 422
aoqi@0 423 /**
aoqi@0 424 * Operation mode.
aoqi@0 425 */
aoqi@0 426 private static enum Mode {
aoqi@0 427 // normal mode. compile the code
aoqi@0 428 CODE,
aoqi@0 429
aoqi@0 430 // dump the signature of the generated code
aoqi@0 431 SIGNATURE,
aoqi@0 432
aoqi@0 433 // dump DOMForest
aoqi@0 434 FOREST,
aoqi@0 435
aoqi@0 436 // same as CODE but don't produce any Java source code
aoqi@0 437 DRYRUN,
aoqi@0 438
aoqi@0 439 // same as CODE but pack all the outputs into a zip and dumps to stdout
aoqi@0 440 ZIP,
aoqi@0 441
aoqi@0 442 // testing a new binding mode
aoqi@0 443 GBIND
aoqi@0 444 }
aoqi@0 445
aoqi@0 446
aoqi@0 447 /**
aoqi@0 448 * Command-line arguments processor.
aoqi@0 449 *
aoqi@0 450 * <p>
aoqi@0 451 * This class contains options that only make sense
aoqi@0 452 * for the command line interface.
aoqi@0 453 */
aoqi@0 454 static class OptionsEx extends Options
aoqi@0 455 {
aoqi@0 456 /** Operation mode. */
aoqi@0 457 protected Mode mode = Mode.CODE;
aoqi@0 458
aoqi@0 459 /** A switch that determines the behavior in the BGM mode. */
aoqi@0 460 public boolean noNS = false;
aoqi@0 461
aoqi@0 462 /** Parse XJC-specific options. */
aoqi@0 463 @Override
aoqi@0 464 public int parseArgument(String[] args, int i) throws BadCommandLineException {
aoqi@0 465 if (args[i].equals("-noNS")) {
aoqi@0 466 noNS = true;
aoqi@0 467 return 1;
aoqi@0 468 }
aoqi@0 469 if (args[i].equals("-mode")) {
aoqi@0 470 i++;
aoqi@0 471 if (i == args.length)
aoqi@0 472 throw new BadCommandLineException(
aoqi@0 473 Messages.format(Messages.MISSING_MODE_OPERAND));
aoqi@0 474
aoqi@0 475 String mstr = args[i].toLowerCase();
aoqi@0 476
aoqi@0 477 for( Mode m : Mode.values() ) {
aoqi@0 478 if(m.name().toLowerCase().startsWith(mstr) && mstr.length()>2) {
aoqi@0 479 mode = m;
aoqi@0 480 return 2;
aoqi@0 481 }
aoqi@0 482 }
aoqi@0 483
aoqi@0 484 throw new BadCommandLineException(
aoqi@0 485 Messages.format(Messages.UNRECOGNIZED_MODE, args[i]));
aoqi@0 486 }
aoqi@0 487 if (args[i].equals("-help")) {
aoqi@0 488 usage(this,false);
aoqi@0 489 throw new WeAreDone();
aoqi@0 490 }
aoqi@0 491 if (args[i].equals("-private")) {
aoqi@0 492 usage(this,true);
aoqi@0 493 throw new WeAreDone();
aoqi@0 494 }
aoqi@0 495
aoqi@0 496 return super.parseArgument(args, i);
aoqi@0 497 }
aoqi@0 498 }
aoqi@0 499
aoqi@0 500 /**
aoqi@0 501 * Used to signal that we've finished processing.
aoqi@0 502 */
aoqi@0 503 private static final class WeAreDone extends BadCommandLineException {}
aoqi@0 504
aoqi@0 505
aoqi@0 506 /**
aoqi@0 507 * Prints the usage screen and exits the process.
aoqi@0 508 *
aoqi@0 509 * @param opts
aoqi@0 510 * If the parsing of options have started, set a partly populated
aoqi@0 511 * {@link Options} object.
aoqi@0 512 */
aoqi@0 513 public static void usage( @Nullable Options opts, boolean privateUsage ) {
aoqi@0 514 System.out.println(Messages.format(Messages.DRIVER_PUBLIC_USAGE));
aoqi@0 515 if (privateUsage) {
aoqi@0 516 System.out.println(Messages.format(Messages.DRIVER_PRIVATE_USAGE));
aoqi@0 517 }
aoqi@0 518
aoqi@0 519 if( opts!=null && !opts.getAllPlugins().isEmpty()) {
aoqi@0 520 System.out.println(Messages.format(Messages.ADDON_USAGE));
aoqi@0 521 for (Plugin p : opts.getAllPlugins()) {
aoqi@0 522 System.out.println(p.getUsage());
aoqi@0 523 }
aoqi@0 524 }
aoqi@0 525 }
aoqi@0 526 }

mercurial