jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java
changeset 43852 93a527059d8a
parent 43127 33b8f6646c21
child 45678 65fdff10664d
equal deleted inserted replaced
43752:3c68ef249093 43852:93a527059d8a
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.internal.xjc;
    26 package com.sun.tools.internal.xjc;
    27 
    27 
       
    28 import java.io.BufferedReader;
       
    29 import java.io.File;
       
    30 import java.io.FileInputStream;
       
    31 import java.io.IOException;
       
    32 import java.io.InputStreamReader;
       
    33 import java.io.PrintWriter;
       
    34 import java.io.StringWriter;
       
    35 import java.net.MalformedURLException;
       
    36 import java.net.URL;
       
    37 import java.net.URLClassLoader;
       
    38 import java.security.AccessController;
       
    39 import java.security.PrivilegedAction;
       
    40 import java.text.SimpleDateFormat;
       
    41 import java.util.ArrayList;
       
    42 import java.util.Date;
       
    43 import java.util.Enumeration;
       
    44 import java.util.HashSet;
       
    45 import java.util.List;
       
    46 import java.util.ServiceLoader;
       
    47 import java.util.Set;
       
    48 
    28 import com.sun.codemodel.internal.CodeWriter;
    49 import com.sun.codemodel.internal.CodeWriter;
    29 import com.sun.codemodel.internal.JPackage;
    50 import com.sun.codemodel.internal.JPackage;
    30 import com.sun.codemodel.internal.JResourceFile;
    51 import com.sun.codemodel.internal.JResourceFile;
    31 import com.sun.codemodel.internal.writer.FileCodeWriter;
    52 import com.sun.codemodel.internal.writer.FileCodeWriter;
    32 import com.sun.codemodel.internal.writer.PrologCodeWriter;
    53 import com.sun.codemodel.internal.writer.PrologCodeWriter;
    35 import com.sun.tools.internal.xjc.api.SpecVersion;
    56 import com.sun.tools.internal.xjc.api.SpecVersion;
    36 import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
    57 import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
    37 import com.sun.tools.internal.xjc.model.Model;
    58 import com.sun.tools.internal.xjc.model.Model;
    38 import com.sun.tools.internal.xjc.reader.Util;
    59 import com.sun.tools.internal.xjc.reader.Util;
    39 import com.sun.xml.internal.bind.api.impl.NameConverter;
    60 import com.sun.xml.internal.bind.api.impl.NameConverter;
       
    61 import java.net.URI;
       
    62 import java.net.URISyntaxException;
       
    63 import java.nio.charset.Charset;
       
    64 import java.nio.charset.IllegalCharsetNameException;
       
    65 import java.util.Locale;
       
    66 import java.util.logging.Level;
       
    67 import java.util.logging.Logger;
       
    68 
    40 import org.xml.sax.EntityResolver;
    69 import org.xml.sax.EntityResolver;
    41 import org.xml.sax.InputSource;
    70 import org.xml.sax.InputSource;
    42 
       
    43 import java.io.BufferedReader;
       
    44 import java.io.File;
       
    45 import java.io.FileInputStream;
       
    46 import java.io.IOException;
       
    47 import java.io.InputStreamReader;
       
    48 import java.io.PrintWriter;
       
    49 import java.io.StringWriter;
       
    50 import java.net.MalformedURLException;
       
    51 import java.net.URI;
       
    52 import java.net.URISyntaxException;
       
    53 import java.net.URL;
       
    54 import java.net.URLClassLoader;
       
    55 import java.nio.charset.Charset;
       
    56 import java.nio.charset.IllegalCharsetNameException;
       
    57 import java.security.AccessController;
       
    58 import java.security.PrivilegedAction;
       
    59 import java.text.SimpleDateFormat;
       
    60 import java.util.ArrayList;
       
    61 import java.util.Date;
       
    62 import java.util.Enumeration;
       
    63 import java.util.HashSet;
       
    64 import java.util.List;
       
    65 import java.util.Locale;
       
    66 import java.util.ServiceLoader;
       
    67 import java.util.Set;
       
    68 import java.util.logging.Level;
       
    69 import java.util.logging.Logger;
       
    70 
       
    71 import javax.xml.catalog.CatalogFeatures;
       
    72 import javax.xml.catalog.CatalogFeatures.Feature;
       
    73 import javax.xml.catalog.CatalogManager;
       
    74 
    71 
    75 /**
    72 /**
    76  * Global options.
    73  * Global options.
    77  *
    74  *
    78  * <p>
    75  * <p>
   179      * {@link JPackage#addResourceFile(JResourceFile)}.
   176      * {@link JPackage#addResourceFile(JResourceFile)}.
   180      */
   177      */
   181     public File targetDir = new File(".");
   178     public File targetDir = new File(".");
   182 
   179 
   183     /**
   180     /**
   184      * Actually stores {@link CatalogResolver}, but the field
   181      * On JDK 8 an odler stores {@code CatalogResolver}, but the field
   185      * type is made to {@link EntityResolver} so that XJC can be
   182      * type is made to {@link EntityResolver} so that XJC can be
   186      * used even if resolver.jar is not available in the classpath.
   183      * used even if resolver.jar is not available in the classpath.
   187      */
   184      */
   188     public EntityResolver entityResolver = null;
   185     public EntityResolver entityResolver = null;
   189 
   186 
   206     public String defaultPackage2 = null;
   203     public String defaultPackage2 = null;
   207 
   204 
   208     /**
   205     /**
   209      * Input schema files as a list of {@link InputSource}s.
   206      * Input schema files as a list of {@link InputSource}s.
   210      */
   207      */
   211     private final List<InputSource> grammars = new ArrayList<InputSource>();
   208     private final List<InputSource> grammars = new ArrayList<>();
   212 
   209 
   213     private final List<InputSource> bindFiles = new ArrayList<InputSource>();
   210     private final List<InputSource> bindFiles = new ArrayList<>();
   214 
   211 
   215     // Proxy setting.
   212     // Proxy setting.
   216     private String proxyHost = null;
   213     private String proxyHost = null;
   217     private String proxyPort = null;
   214     private String proxyPort = null;
   218     public String proxyAuth = null;
   215     public String proxyAuth = null;
   219 
   216 
   220     /**
   217     /**
   221      * {@link Plugin}s that are enabled in this compilation.
   218      * {@link Plugin}s that are enabled in this compilation.
   222      */
   219      */
   223     public final List<Plugin> activePlugins = new ArrayList<Plugin>();
   220     public final List<Plugin> activePlugins = new ArrayList<>();
   224 
   221 
   225     /**
   222     /**
   226      * All discovered {@link Plugin}s.
   223      * All discovered {@link Plugin}s.
   227      * This is lazily parsed, so that we can take '-cp' option into account.
   224      * This is lazily parsed, so that we can take '-cp' option into account.
   228      *
   225      *
   231     private List<Plugin> allPlugins;
   228     private List<Plugin> allPlugins;
   232 
   229 
   233     /**
   230     /**
   234      * Set of URIs that plug-ins recognize as extension bindings.
   231      * Set of URIs that plug-ins recognize as extension bindings.
   235      */
   232      */
   236     public final Set<String> pluginURIs = new HashSet<String>();
   233     public final Set<String> pluginURIs = new HashSet<>();
   237 
   234 
   238     /**
   235     /**
   239      * This allocator has the final say on deciding the class name.
   236      * This allocator has the final say on deciding the class name.
   240      */
   237      */
   241     public ClassNameAllocator classNameAllocator;
   238     public ClassNameAllocator classNameAllocator;
   355      *
   352      *
   356      * <p>
   353      * <p>
   357      * A plugins are enumerated when this method is called for the first time,
   354      * A plugins are enumerated when this method is called for the first time,
   358      * by taking {@link #classpaths} into account. That means
   355      * by taking {@link #classpaths} into account. That means
   359      * "-cp plugin.jar" has to come before you specify options to enable it.
   356      * "-cp plugin.jar" has to come before you specify options to enable it.
       
   357      * @return
   360      */
   358      */
   361     public List<Plugin> getAllPlugins() {
   359     public List<Plugin> getAllPlugins() {
   362         if(allPlugins==null) {
   360         if(allPlugins==null) {
   363             allPlugins = findServices(Plugin.class);
   361             allPlugins = findServices(Plugin.class);
   364         }
   362         }
   373     }
   371     }
   374     public void setSchemaLanguage(Language _schemaLanguage) {
   372     public void setSchemaLanguage(Language _schemaLanguage) {
   375         this.schemaLanguage = _schemaLanguage;
   373         this.schemaLanguage = _schemaLanguage;
   376     }
   374     }
   377 
   375 
   378     /** Input schema files. */
   376     /** Input schema files.
       
   377      * @return  */
   379     public InputSource[] getGrammars() {
   378     public InputSource[] getGrammars() {
   380         return grammars.toArray(new InputSource[grammars.size()]);
   379         return grammars.toArray(new InputSource[grammars.size()]);
   381     }
   380     }
   382 
   381 
   383     /**
   382     /**
   384      * Adds a new input schema.
   383      * Adds a new input schema.
       
   384      * @param is
   385      */
   385      */
   386     public void addGrammar( InputSource is ) {
   386     public void addGrammar( InputSource is ) {
   387         grammars.add(absolutize(is));
   387         grammars.add(absolutize(is));
   388     }
   388     }
   389 
   389 
   400         addGrammar(fileToInputSource(source));
   400         addGrammar(fileToInputSource(source));
   401     }
   401     }
   402 
   402 
   403     /**
   403     /**
   404      * Recursively scan directories and add all XSD files in it.
   404      * Recursively scan directories and add all XSD files in it.
       
   405      * @param dir
   405      */
   406      */
   406     public void addGrammarRecursive( File dir ) {
   407     public void addGrammarRecursive( File dir ) {
   407         addRecursive(dir,".xsd",grammars);
   408         addRecursive(dir,".xsd",grammars);
   408     }
   409     }
   409 
   410 
   430             logger.log(Level.FINE, "{0}, {1}", new Object[]{is.getSystemId(), e.getLocalizedMessage()});
   431             logger.log(Level.FINE, "{0}, {1}", new Object[]{is.getSystemId(), e.getLocalizedMessage()});
   431         }
   432         }
   432         return is;
   433         return is;
   433     }
   434     }
   434 
   435 
   435     /** Input external binding files. */
   436     /** Input external binding files.
       
   437      * @return  */
   436     public InputSource[] getBindFiles() {
   438     public InputSource[] getBindFiles() {
   437         return bindFiles.toArray(new InputSource[bindFiles.size()]);
   439         return bindFiles.toArray(new InputSource[bindFiles.size()]);
   438     }
   440     }
   439 
   441 
   440     /**
   442     /**
   441      * Adds a new binding file.
   443      * Adds a new binding file.
       
   444      * @param is
   442      */
   445      */
   443     public void addBindFile( InputSource is ) {
   446     public void addBindFile( InputSource is ) {
   444         bindFiles.add(absolutize(is));
   447         bindFiles.add(absolutize(is));
   445     }
   448     }
   446 
   449 
   447     /**
   450     /**
   448      * Adds a new binding file.
   451      * Adds a new binding file.
       
   452      * @param bindFile
   449      */
   453      */
   450     public void addBindFile( File bindFile ) {
   454     public void addBindFile( File bindFile ) {
   451         bindFiles.add(fileToInputSource(bindFile));
   455         bindFiles.add(fileToInputSource(bindFile));
   452     }
   456     }
   453 
   457 
   454     /**
   458     /**
   455      * Recursively scan directories and add all ".xjb" files in it.
   459      * Recursively scan directories and add all ".xjb" files in it.
       
   460      * @param dir
   456      */
   461      */
   457     public void addBindFileRecursive( File dir ) {
   462     public void addBindFileRecursive( File dir ) {
   458         addRecursive(dir,".xjb",bindFiles);
   463         addRecursive(dir,".xjb",bindFiles);
   459     }
   464     }
   460 
   465 
   461     public final List<URL> classpaths = new ArrayList<URL>();
   466     public final List<URL> classpaths = new ArrayList<>();
   462     /**
   467     /**
   463      * Gets a classLoader that can load classes specified via the
   468      * Gets a classLoader that can load classes specified via the
   464      * -classpath option.
   469      * -classpath option.
       
   470      * @param parent
       
   471      * @return
   465      */
   472      */
   466     public ClassLoader getUserClassLoader( ClassLoader parent ) {
   473     public ClassLoader getUserClassLoader( ClassLoader parent ) {
   467         if (classpaths.isEmpty())
   474         if (classpaths.isEmpty())
   468             return parent;
   475             return parent;
   469         return new URLClassLoader(
   476         return new URLClassLoader(
   480 
   487 
   481     /**
   488     /**
   482      * Parses an option {@code args[i]} and return
   489      * Parses an option {@code args[i]} and return
   483      * the number of tokens consumed.
   490      * the number of tokens consumed.
   484      *
   491      *
       
   492      * @param args
       
   493      * @param i
   485      * @return
   494      * @return
   486      *      0 if the argument is not understood. Returning 0
   495      *      0 if the argument is not understood. Returning 0
   487      *      will let the caller report an error.
   496      *      will let the caller report an error.
   488      * @exception BadCommandLineException
   497      * @exception BadCommandLineException
   489      *      If the callee wants to provide a custom message for an error.
   498      *      If the callee wants to provide a custom message for an error.
   608             if(!file.exists()) {
   617             if(!file.exists()) {
   609                 throw new BadCommandLineException(
   618                 throw new BadCommandLineException(
   610                     Messages.format(Messages.NO_SUCH_FILE,file));
   619                     Messages.format(Messages.NO_SUCH_FILE,file));
   611             }
   620             }
   612 
   621 
   613             try {
   622             try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"))) {
   614                 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
       
   615                 parseProxy(in.readLine());
   623                 parseProxy(in.readLine());
   616                 in.close();
       
   617             } catch (IOException e) {
   624             } catch (IOException e) {
   618                 throw new BadCommandLineException(
   625                 throw new BadCommandLineException(
   619                     Messages.format(Messages.FAILED_TO_PARSE,file,e.getMessage()),e);
   626                     Messages.format(Messages.FAILED_TO_PARSE,file,e.getMessage()),e);
   620             }
   627             }
   621 
   628 
   637         if (args[i].equals("-port")) {
   644         if (args[i].equals("-port")) {
   638             proxyPort = requireArgument("-port",args,++i);
   645             proxyPort = requireArgument("-port",args,++i);
   639             return 2;
   646             return 2;
   640         }
   647         }
   641         if( args[i].equals("-catalog") ) {
   648         if( args[i].equals("-catalog") ) {
   642             // use javax.xml.catalog to resolve external entities.
   649             // use Sun's "XML Entity and URI Resolvers" by Norman Walsh
       
   650             // to resolve external entities.
       
   651             // https://xerces.apache.org/xml-commons/components/resolver/resolver-article.html
   643 
   652 
   644             File catalogFile = new File(requireArgument("-catalog",args,++i));
   653             File catalogFile = new File(requireArgument("-catalog",args,++i));
   645             try {
   654             try {
   646                 addCatalog(catalogFile);
   655                 addCatalog(catalogFile);
   647             } catch (IOException e) {
   656             } catch (IOException e) {
   650             }
   659             }
   651             return 2;
   660             return 2;
   652         }
   661         }
   653         if( args[i].equals("-Xtest-class-name-allocator") ) {
   662         if( args[i].equals("-Xtest-class-name-allocator") ) {
   654             classNameAllocator = new ClassNameAllocator() {
   663             classNameAllocator = new ClassNameAllocator() {
       
   664                 @Override
   655                 public String assignClassName(String packageName, String className) {
   665                 public String assignClassName(String packageName, String className) {
   656                     System.out.printf("assignClassName(%s,%s)\n",packageName,className);
   666                     System.out.printf("assignClassName(%s,%s)\n",packageName,className);
   657                     return className+"_Type";
   667                     return className+"_Type";
   658                 }
   668                 }
   659             };
   669             };
   734         }
   744         }
   735     }
   745     }
   736 
   746 
   737     /**
   747     /**
   738      * Obtains an operand and reports an error if it's not there.
   748      * Obtains an operand and reports an error if it's not there.
       
   749      * @param optionName
       
   750      * @param args
       
   751      * @param i
       
   752      * @return
       
   753      * @throws com.sun.tools.internal.xjc.BadCommandLineException
   739      */
   754      */
   740     public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException {
   755     public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException {
   741         if (i == args.length || args[i].startsWith("-")) {
   756         if (i == args.length || args[i].startsWith("-")) {
   742             throw new BadCommandLineException(
   757             throw new BadCommandLineException(
   743                 Messages.format(Messages.MISSING_OPERAND,optionName));
   758                 Messages.format(Messages.MISSING_OPERAND,optionName));
   771                 target.add(absolutize(fileToInputSource(fsrc)));
   786                 target.add(absolutize(fileToInputSource(fsrc)));
   772             }
   787             }
   773         }
   788         }
   774     }
   789     }
   775 
   790 
   776     /**
       
   777      * Adds a new catalog file.
       
   778      */
       
   779     public void addCatalog(File catalogFile) throws IOException {
       
   780         URI newUrl = catalogFile.toURI();
       
   781         if (!catalogUrls.contains(newUrl)) {
       
   782             catalogUrls.add(newUrl);
       
   783         }
       
   784         try {
       
   785             entityResolver = CatalogManager.catalogResolver(catalogFeatures,
       
   786                                 catalogUrls.stream().toArray(URI[]::new));
       
   787         } catch (Exception ex) {
       
   788             entityResolver = null;
       
   789         }
       
   790     }
       
   791 
       
   792     // Since javax.xml.catalog is unmodifiable we need to track catalog
   791     // Since javax.xml.catalog is unmodifiable we need to track catalog
   793     // URLs added and create new catalog each time addCatalog is called
   792     // URLs added and create new catalog each time addCatalog is called
   794     private final ArrayList<URI> catalogUrls = new ArrayList<>();
   793     private final ArrayList<URI> catalogUrls = new ArrayList<>();
   795 
   794 
   796     // Cache CatalogFeatures instance for future usages.
   795     /**
   797     // Resolve feature is set to "continue" value for backward compatibility.
   796      * Adds a new catalog file.Use created or existed resolver to parse new catalog file.
   798     private static CatalogFeatures catalogFeatures = CatalogFeatures.builder()
   797      * @param catalogFile
   799                                                     .with(Feature.RESOLVE, "continue")
   798      * @throws java.io.IOException
   800                                                     .build();
   799      */
       
   800     public void addCatalog(File catalogFile) throws IOException {
       
   801         URI newUri = catalogFile.toURI();
       
   802         if (!catalogUrls.contains(newUri)) {
       
   803             catalogUrls.add(newUri);
       
   804         }
       
   805         entityResolver = CatalogUtil.getCatalog(entityResolver, catalogFile, catalogUrls);
       
   806     }
       
   807 
   801     /**
   808     /**
   802      * Parses arguments and fill fields of this object.
   809      * Parses arguments and fill fields of this object.
   803      *
   810      *
       
   811      * @param args
   804      * @exception BadCommandLineException
   812      * @exception BadCommandLineException
   805      *      thrown when there's a problem in the command-line arguments
   813      *      thrown when there's a problem in the command-line arguments
   806      */
   814      */
   807     public void parseArguments( String[] args ) throws BadCommandLineException {
   815     public void parseArguments( String[] args ) throws BadCommandLineException {
   808 
   816 
   859                 Messages.format(Messages.PLUGIN_LOAD_FAILURE,pluginLoadFailure));
   867                 Messages.format(Messages.PLUGIN_LOAD_FAILURE,pluginLoadFailure));
   860     }
   868     }
   861 
   869 
   862     /**
   870     /**
   863      * Finds the {@code META-INF/sun-jaxb.episode} file to add as a binding customization.
   871      * Finds the {@code META-INF/sun-jaxb.episode} file to add as a binding customization.
       
   872      * @param jar
       
   873      * @throws com.sun.tools.internal.xjc.BadCommandLineException
   864      */
   874      */
   865     public void scanEpisodeFile(File jar) throws BadCommandLineException {
   875     public void scanEpisodeFile(File jar) throws BadCommandLineException {
   866         try {
   876         try {
   867             URLClassLoader ucl = new URLClassLoader(new URL[]{jar.toURL()});
   877             URLClassLoader ucl = new URLClassLoader(new URL[]{jar.toURL()});
   868             Enumeration<URL> resources = ucl.findResources("META-INF/sun-jaxb.episode");
   878             Enumeration<URL> resources = ucl.findResources("META-INF/sun-jaxb.episode");
   877     }
   887     }
   878 
   888 
   879 
   889 
   880     /**
   890     /**
   881      * Guesses the schema language.
   891      * Guesses the schema language.
       
   892      * @return
   882      */
   893      */
   883     public Language guessSchemaLanguage() {
   894     public Language guessSchemaLanguage() {
   884 
   895 
   885         // otherwise, use the file extension.
   896         // otherwise, use the file extension.
   886         // not a good solution, but very easy.
   897         // not a good solution, but very easy.
   897         return Language.XMLSCHEMA;
   908         return Language.XMLSCHEMA;
   898     }
   909     }
   899 
   910 
   900     /**
   911     /**
   901      * Creates a configured CodeWriter that produces files into the specified directory.
   912      * Creates a configured CodeWriter that produces files into the specified directory.
       
   913      * @return
       
   914      * @throws java.io.IOException
   902      */
   915      */
   903     public CodeWriter createCodeWriter() throws IOException {
   916     public CodeWriter createCodeWriter() throws IOException {
   904         return createCodeWriter(new FileCodeWriter( targetDir, readOnly, encoding ));
   917         return createCodeWriter(new FileCodeWriter( targetDir, readOnly, encoding ));
   905     }
   918     }
   906 
   919 
   907     /**
   920     /**
   908      * Creates a configured CodeWriter that produces files into the specified directory.
   921      * Creates a configured CodeWriter that produces files into the specified directory.
       
   922      * @param core
       
   923      * @return
   909      */
   924      */
   910     public CodeWriter createCodeWriter( CodeWriter core ) {
   925     public CodeWriter createCodeWriter( CodeWriter core ) {
   911         if(noFileHeader)
   926         if(noFileHeader)
   912             return core;
   927             return core;
   913 
   928 
   914         return new PrologCodeWriter( core,getPrologComment() );
   929         return new PrologCodeWriter( core,getPrologComment() );
   915     }
   930     }
   916 
   931 
   917     /**
   932     /**
   918      * Gets the string suitable to be used as the prolog comment baked into artifacts.
   933      * Gets the string suitable to be used as the prolog comment baked into artifacts.This is the string like "This file was generated by the JAXB RI on YYYY/mm/dd..."
   919      * This is the string like "This file was generated by the JAXB RI on YYYY/mm/dd..."
   934      * @return
   920      */
   935      */
   921     public String getPrologComment() {
   936     public String getPrologComment() {
   922         // generate format syntax: <date> 'at' <time>
   937         // generate format syntax: <date> 'at' <time>
   923         String format =
   938         String format =
   924             Messages.format(Messages.DATE_FORMAT)
   939             Messages.format(Messages.DATE_FORMAT)
   941     /**
   956     /**
   942      * Looks for all "META-INF/services/[className]" files and
   957      * Looks for all "META-INF/services/[className]" files and
   943      * create one instance for each class name found inside this file.
   958      * create one instance for each class name found inside this file.
   944      */
   959      */
   945     private <T> List<T> findServices( Class<T> clazz) {
   960     private <T> List<T> findServices( Class<T> clazz) {
   946         final List<T> result = new ArrayList<T>();
   961         final List<T> result = new ArrayList<>();
   947         final boolean debug = getDebugPropertyValue();
   962         final boolean debug = getDebugPropertyValue();
   948         try {
   963         try {
   949             // TCCL allows user plugins to be loaded even if xjc is in jdk
   964             // TCCL allows user plugins to be loaded even if xjc is in jdk
   950             // We have to use our SecureLoader to obtain it because we are trying to avoid SecurityException
   965             // We have to use our SecureLoader to obtain it because we are trying to avoid SecurityException
   951             final ClassLoader tccl = SecureLoader.getContextClassLoader();
   966             final ClassLoader tccl = SecureLoader.getContextClassLoader();