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

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

mercurial