1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,1048 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.internal.xjc; 1.30 + 1.31 +import java.io.BufferedReader; 1.32 +import java.io.File; 1.33 +import java.io.FileInputStream; 1.34 +import java.io.IOException; 1.35 +import java.io.InputStreamReader; 1.36 +import java.io.PrintWriter; 1.37 +import java.io.StringWriter; 1.38 +import java.lang.reflect.Array; 1.39 +import java.lang.reflect.InvocationTargetException; 1.40 +import java.net.MalformedURLException; 1.41 +import java.net.URL; 1.42 +import java.net.URLClassLoader; 1.43 +import java.text.SimpleDateFormat; 1.44 +import java.util.ArrayList; 1.45 +import java.util.Arrays; 1.46 +import java.util.Date; 1.47 +import java.util.Enumeration; 1.48 +import java.util.HashSet; 1.49 +import java.util.List; 1.50 +import java.util.Set; 1.51 +import java.util.regex.Matcher; 1.52 +import java.util.regex.Pattern; 1.53 + 1.54 +import com.sun.codemodel.internal.CodeWriter; 1.55 +import com.sun.codemodel.internal.JPackage; 1.56 +import com.sun.codemodel.internal.writer.FileCodeWriter; 1.57 +import com.sun.codemodel.internal.writer.PrologCodeWriter; 1.58 +import com.sun.org.apache.xml.internal.resolver.CatalogManager; 1.59 +import com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver; 1.60 +import com.sun.tools.internal.xjc.api.ClassNameAllocator; 1.61 +import com.sun.tools.internal.xjc.api.SpecVersion; 1.62 +import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory; 1.63 +import com.sun.tools.internal.xjc.model.Model; 1.64 +import com.sun.tools.internal.xjc.reader.Util; 1.65 +import com.sun.xml.internal.bind.api.impl.NameConverter; 1.66 +import java.net.URI; 1.67 +import java.net.URISyntaxException; 1.68 +import java.nio.charset.Charset; 1.69 +import java.nio.charset.IllegalCharsetNameException; 1.70 +import java.util.Locale; 1.71 +import java.util.logging.Level; 1.72 +import java.util.logging.Logger; 1.73 + 1.74 +import org.xml.sax.EntityResolver; 1.75 +import org.xml.sax.InputSource; 1.76 + 1.77 +/** 1.78 + * Global options. 1.79 + * 1.80 + * <p> 1.81 + * This class stores invocation configuration for XJC. 1.82 + * The configuration in this class should be abstract enough so that 1.83 + * it could be parsed from both command-line or Ant. 1.84 + */ 1.85 +public class Options 1.86 +{ 1.87 + /** If "-debug" is specified. */ 1.88 + public boolean debugMode; 1.89 + 1.90 + /** If the "-verbose" option is specified. */ 1.91 + public boolean verbose; 1.92 + 1.93 + /** If the "-quiet" option is specified. */ 1.94 + public boolean quiet; 1.95 + 1.96 + /** If the -readOnly option is specified. */ 1.97 + public boolean readOnly; 1.98 + 1.99 + /** No file header comment (to be more friendly with diff.) */ 1.100 + public boolean noFileHeader; 1.101 + 1.102 + /** When on, fixes getter/setter generation to match the Bean Introspection API */ 1.103 + public boolean enableIntrospection; 1.104 + 1.105 + /** When on, generates content property for types with multiple xs:any derived elements (which is supposed to be correct behaviour) */ 1.106 + public boolean contentForWildcard; 1.107 + 1.108 + /** Encoding to be used by generated java sources, null for platform default. */ 1.109 + public String encoding; 1.110 + 1.111 + /** 1.112 + * Check the source schemas with extra scrutiny. 1.113 + * The exact meaning depends on the schema language. 1.114 + */ 1.115 + public boolean strictCheck =true; 1.116 + 1.117 + /** 1.118 + * If -explicit-annotation option is specified. 1.119 + * <p> 1.120 + * This generates code that works around issues specific to 1.4 runtime. 1.121 + */ 1.122 + public boolean runtime14 = false; 1.123 + 1.124 + /** 1.125 + * If true, try to resolve name conflicts automatically by assigning mechanical numbers. 1.126 + */ 1.127 + public boolean automaticNameConflictResolution = false; 1.128 + 1.129 + /** 1.130 + * strictly follow the compatibility rules and reject schemas that 1.131 + * contain features from App. E.2, use vendor binding extensions 1.132 + */ 1.133 + public static final int STRICT = 1; 1.134 + /** 1.135 + * loosely follow the compatibility rules and allow the use of vendor 1.136 + * binding extensions 1.137 + */ 1.138 + public static final int EXTENSION = 2; 1.139 + 1.140 + /** 1.141 + * this switch determines how carefully the compiler will follow 1.142 + * the compatibility rules in the spec. Either <code>STRICT</code> 1.143 + * or <code>EXTENSION</code>. 1.144 + */ 1.145 + public int compatibilityMode = STRICT; 1.146 + 1.147 + public boolean isExtensionMode() { 1.148 + return compatibilityMode==EXTENSION; 1.149 + } 1.150 + 1.151 + private static final Logger logger = com.sun.xml.internal.bind.Util.getClassLogger(); 1.152 + 1.153 + /** 1.154 + * Generates output for the specified version of the runtime. 1.155 + */ 1.156 + public SpecVersion target = SpecVersion.LATEST; 1.157 + 1.158 + private boolean is2_2 = true; 1.159 + 1.160 + public Options() { 1.161 + if (is2_2) { 1.162 + try { 1.163 + Class.forName("javax.xml.bind.JAXBPermission"); 1.164 + } catch (ClassNotFoundException cnfe) { 1.165 + is2_2 = false; 1.166 + } 1.167 + if (!is2_2) { 1.168 + target = SpecVersion.V2_1; 1.169 + } else { 1.170 + target = SpecVersion.LATEST; 1.171 + } 1.172 + } 1.173 + } 1.174 + 1.175 + /** 1.176 + * Target directory when producing files. 1.177 + * <p> 1.178 + * This field is not used when XJC is driven through the XJC API. 1.179 + * Plugins that need to generate extra files should do so by using 1.180 + * {@link JPackage#addResourceFile(JResourceFile)}. 1.181 + */ 1.182 + public File targetDir = new File("."); 1.183 + 1.184 + /** 1.185 + * Actually stores {@link CatalogResolver}, but the field 1.186 + * type is made to {@link EntityResolver} so that XJC can be 1.187 + * used even if resolver.jar is not available in the classpath. 1.188 + */ 1.189 + public EntityResolver entityResolver = null; 1.190 + 1.191 + /** 1.192 + * Type of input schema language. One of the <code>SCHEMA_XXX</code> 1.193 + * constants. 1.194 + */ 1.195 + private Language schemaLanguage = null; 1.196 + 1.197 + /** 1.198 + * The -p option that should control the default Java package that 1.199 + * will contain the generated code. Null if unspecified. 1.200 + */ 1.201 + public String defaultPackage = null; 1.202 + 1.203 + /** 1.204 + * Similar to the -p option, but this one works with a lower priority, 1.205 + * and customizations overrides this. Used by JAX-RPC. 1.206 + */ 1.207 + public String defaultPackage2 = null; 1.208 + 1.209 + /** 1.210 + * Input schema files as a list of {@link InputSource}s. 1.211 + */ 1.212 + private final List<InputSource> grammars = new ArrayList<InputSource>(); 1.213 + 1.214 + private final List<InputSource> bindFiles = new ArrayList<InputSource>(); 1.215 + 1.216 + // Proxy setting. 1.217 + private String proxyHost = null; 1.218 + private String proxyPort = null; 1.219 + private String proxyUser = null; 1.220 + private String proxyPassword = null; 1.221 + 1.222 + /** 1.223 + * {@link Plugin}s that are enabled in this compilation. 1.224 + */ 1.225 + public final List<Plugin> activePlugins = new ArrayList<Plugin>(); 1.226 + 1.227 + /** 1.228 + * All discovered {@link Plugin}s. 1.229 + * This is lazily parsed, so that we can take '-cp' option into account. 1.230 + * 1.231 + * @see #getAllPlugins() 1.232 + */ 1.233 + private List<Plugin> allPlugins; 1.234 + 1.235 + /** 1.236 + * Set of URIs that plug-ins recognize as extension bindings. 1.237 + */ 1.238 + public final Set<String> pluginURIs = new HashSet<String>(); 1.239 + 1.240 + /** 1.241 + * This allocator has the final say on deciding the class name. 1.242 + */ 1.243 + public ClassNameAllocator classNameAllocator; 1.244 + 1.245 + /** 1.246 + * This switch controls whether or not xjc will generate package level annotations 1.247 + */ 1.248 + public boolean packageLevelAnnotations = true; 1.249 + 1.250 + /** 1.251 + * This {@link FieldRendererFactory} determines how the fields are generated. 1.252 + */ 1.253 + private FieldRendererFactory fieldRendererFactory = new FieldRendererFactory(); 1.254 + /** 1.255 + * Used to detect if two {@link Plugin}s try to overwrite {@link #fieldRendererFactory}. 1.256 + */ 1.257 + private Plugin fieldRendererFactoryOwner = null; 1.258 + 1.259 + /** 1.260 + * If this is non-null, we use this {@link NameConverter} over the one 1.261 + * given in the schema/binding. 1.262 + */ 1.263 + private NameConverter nameConverter = null; 1.264 + /** 1.265 + * Used to detect if two {@link Plugin}s try to overwrite {@link #nameConverter}. 1.266 + */ 1.267 + private Plugin nameConverterOwner = null; 1.268 + 1.269 + /** 1.270 + * Gets the active {@link FieldRendererFactory} that shall be used to build {@link Model}. 1.271 + * 1.272 + * @return always non-null. 1.273 + */ 1.274 + public FieldRendererFactory getFieldRendererFactory() { 1.275 + return fieldRendererFactory; 1.276 + } 1.277 + 1.278 + /** 1.279 + * Sets the {@link FieldRendererFactory}. 1.280 + * 1.281 + * <p> 1.282 + * This method is for plugins to call to set a custom {@link FieldRendererFactory}. 1.283 + * 1.284 + * @param frf 1.285 + * The {@link FieldRendererFactory} to be installed. Must not be null. 1.286 + * @param owner 1.287 + * Identifies the plugin that owns this {@link FieldRendererFactory}. 1.288 + * When two {@link Plugin}s try to call this method, this allows XJC 1.289 + * to report it as a user-friendly error message. 1.290 + * 1.291 + * @throws BadCommandLineException 1.292 + * If a conflit happens, this exception carries a user-friendly error 1.293 + * message, indicating a conflict. 1.294 + */ 1.295 + public void setFieldRendererFactory(FieldRendererFactory frf, Plugin owner) throws BadCommandLineException { 1.296 + // since this method is for plugins, make it bit more fool-proof than usual 1.297 + if(frf==null) 1.298 + throw new IllegalArgumentException(); 1.299 + if(fieldRendererFactoryOwner!=null) { 1.300 + throw new BadCommandLineException( 1.301 + Messages.format(Messages.FIELD_RENDERER_CONFLICT, 1.302 + fieldRendererFactoryOwner.getOptionName(), 1.303 + owner.getOptionName() )); 1.304 + } 1.305 + this.fieldRendererFactoryOwner = owner; 1.306 + this.fieldRendererFactory = frf; 1.307 + } 1.308 + 1.309 + 1.310 + /** 1.311 + * Gets the active {@link NameConverter} that shall be used to build {@link Model}. 1.312 + * 1.313 + * @return can be null, in which case it's up to the binding. 1.314 + */ 1.315 + public NameConverter getNameConverter() { 1.316 + return nameConverter; 1.317 + } 1.318 + 1.319 + /** 1.320 + * Sets the {@link NameConverter}. 1.321 + * 1.322 + * <p> 1.323 + * This method is for plugins to call to set a custom {@link NameConverter}. 1.324 + * 1.325 + * @param nc 1.326 + * The {@link NameConverter} to be installed. Must not be null. 1.327 + * @param owner 1.328 + * Identifies the plugin that owns this {@link NameConverter}. 1.329 + * When two {@link Plugin}s try to call this method, this allows XJC 1.330 + * to report it as a user-friendly error message. 1.331 + * 1.332 + * @throws BadCommandLineException 1.333 + * If a conflit happens, this exception carries a user-friendly error 1.334 + * message, indicating a conflict. 1.335 + */ 1.336 + public void setNameConverter(NameConverter nc, Plugin owner) throws BadCommandLineException { 1.337 + // since this method is for plugins, make it bit more fool-proof than usual 1.338 + if(nc==null) 1.339 + throw new IllegalArgumentException(); 1.340 + if(nameConverter!=null) { 1.341 + throw new BadCommandLineException( 1.342 + Messages.format(Messages.NAME_CONVERTER_CONFLICT, 1.343 + nameConverterOwner.getOptionName(), 1.344 + owner.getOptionName() )); 1.345 + } 1.346 + this.nameConverterOwner = owner; 1.347 + this.nameConverter = nc; 1.348 + } 1.349 + 1.350 + /** 1.351 + * Gets all the {@link Plugin}s discovered so far. 1.352 + * 1.353 + * <p> 1.354 + * A plugins are enumerated when this method is called for the first time, 1.355 + * by taking {@link #classpaths} into account. That means 1.356 + * "-cp plugin.jar" has to come before you specify options to enable it. 1.357 + */ 1.358 + public List<Plugin> getAllPlugins() { 1.359 + if(allPlugins==null) { 1.360 + allPlugins = new ArrayList<Plugin>(); 1.361 + ClassLoader ucl = getUserClassLoader(SecureLoader.getClassClassLoader(getClass())); 1.362 + allPlugins.addAll(Arrays.asList(findServices(Plugin.class,ucl))); 1.363 + } 1.364 + 1.365 + return allPlugins; 1.366 + } 1.367 + 1.368 + public Language getSchemaLanguage() { 1.369 + if( schemaLanguage==null) 1.370 + schemaLanguage = guessSchemaLanguage(); 1.371 + return schemaLanguage; 1.372 + } 1.373 + public void setSchemaLanguage(Language _schemaLanguage) { 1.374 + this.schemaLanguage = _schemaLanguage; 1.375 + } 1.376 + 1.377 + /** Input schema files. */ 1.378 + public InputSource[] getGrammars() { 1.379 + return grammars.toArray(new InputSource[grammars.size()]); 1.380 + } 1.381 + 1.382 + /** 1.383 + * Adds a new input schema. 1.384 + */ 1.385 + public void addGrammar( InputSource is ) { 1.386 + grammars.add(absolutize(is)); 1.387 + } 1.388 + 1.389 + private InputSource fileToInputSource( File source ) { 1.390 + try { 1.391 + String url = source.toURL().toExternalForm(); 1.392 + return new InputSource(Util.escapeSpace(url)); 1.393 + } catch (MalformedURLException e) { 1.394 + return new InputSource(source.getPath()); 1.395 + } 1.396 + } 1.397 + 1.398 + public void addGrammar( File source ) { 1.399 + addGrammar(fileToInputSource(source)); 1.400 + } 1.401 + 1.402 + /** 1.403 + * Recursively scan directories and add all XSD files in it. 1.404 + */ 1.405 + public void addGrammarRecursive( File dir ) { 1.406 + addRecursive(dir,".xsd",grammars); 1.407 + } 1.408 + 1.409 + private void addRecursive( File dir, String suffix, List<InputSource> result ) { 1.410 + File[] files = dir.listFiles(); 1.411 + if(files==null) return; // work defensively 1.412 + 1.413 + for( File f : files ) { 1.414 + if(f.isDirectory()) 1.415 + addRecursive(f,suffix,result); 1.416 + else 1.417 + if(f.getPath().endsWith(suffix)) 1.418 + result.add(absolutize(fileToInputSource(f))); 1.419 + } 1.420 + } 1.421 + 1.422 + 1.423 + private InputSource absolutize(InputSource is) { 1.424 + // absolutize all the system IDs in the input, so that we can map system IDs to DOM trees. 1.425 + try { 1.426 + URL baseURL = new File(".").getCanonicalFile().toURL(); 1.427 + is.setSystemId( new URL(baseURL,is.getSystemId()).toExternalForm() ); 1.428 + } catch( IOException e ) { 1.429 + logger.log(Level.FINE, "{0}, {1}", new Object[]{is.getSystemId(), e.getLocalizedMessage()}); 1.430 + } 1.431 + return is; 1.432 + } 1.433 + 1.434 + /** Input external binding files. */ 1.435 + public InputSource[] getBindFiles() { 1.436 + return bindFiles.toArray(new InputSource[bindFiles.size()]); 1.437 + } 1.438 + 1.439 + /** 1.440 + * Adds a new binding file. 1.441 + */ 1.442 + public void addBindFile( InputSource is ) { 1.443 + bindFiles.add(absolutize(is)); 1.444 + } 1.445 + 1.446 + /** 1.447 + * Adds a new binding file. 1.448 + */ 1.449 + public void addBindFile( File bindFile ) { 1.450 + bindFiles.add(fileToInputSource(bindFile)); 1.451 + } 1.452 + 1.453 + /** 1.454 + * Recursively scan directories and add all ".xjb" files in it. 1.455 + */ 1.456 + public void addBindFileRecursive( File dir ) { 1.457 + addRecursive(dir,".xjb",bindFiles); 1.458 + } 1.459 + 1.460 + public final List<URL> classpaths = new ArrayList<URL>(); 1.461 + /** 1.462 + * Gets a classLoader that can load classes specified via the 1.463 + * -classpath option. 1.464 + */ 1.465 + public URLClassLoader getUserClassLoader( ClassLoader parent ) { 1.466 + return new URLClassLoader( 1.467 + classpaths.toArray(new URL[classpaths.size()]),parent); 1.468 + } 1.469 + 1.470 + 1.471 + /** 1.472 + * Parses an option <code>args[i]</code> and return 1.473 + * the number of tokens consumed. 1.474 + * 1.475 + * @return 1.476 + * 0 if the argument is not understood. Returning 0 1.477 + * will let the caller report an error. 1.478 + * @exception BadCommandLineException 1.479 + * If the callee wants to provide a custom message for an error. 1.480 + */ 1.481 + public int parseArgument( String[] args, int i ) throws BadCommandLineException { 1.482 + if (args[i].equals("-classpath") || args[i].equals("-cp")) { 1.483 + String a = requireArgument(args[i], args, ++i); 1.484 + for (String p : a.split(File.pathSeparator)) { 1.485 + File file = new File(p); 1.486 + try { 1.487 + classpaths.add(file.toURL()); 1.488 + } catch (MalformedURLException e) { 1.489 + throw new BadCommandLineException( 1.490 + Messages.format(Messages.NOT_A_VALID_FILENAME,file),e); 1.491 + } 1.492 + } 1.493 + return 2; 1.494 + } 1.495 + if (args[i].equals("-d")) { 1.496 + targetDir = new File(requireArgument("-d",args,++i)); 1.497 + if( !targetDir.exists() ) 1.498 + throw new BadCommandLineException( 1.499 + Messages.format(Messages.NON_EXISTENT_DIR,targetDir)); 1.500 + return 2; 1.501 + } 1.502 + if (args[i].equals("-readOnly")) { 1.503 + readOnly = true; 1.504 + return 1; 1.505 + } 1.506 + if (args[i].equals("-p")) { 1.507 + defaultPackage = requireArgument("-p",args,++i); 1.508 + if(defaultPackage.length()==0) { // user specified default package 1.509 + // there won't be any package to annotate, so disable them 1.510 + // automatically as a usability feature 1.511 + packageLevelAnnotations = false; 1.512 + } 1.513 + return 2; 1.514 + } 1.515 + if (args[i].equals("-debug")) { 1.516 + debugMode = true; 1.517 + verbose = true; 1.518 + return 1; 1.519 + } 1.520 + if (args[i].equals("-nv")) { 1.521 + strictCheck = false; 1.522 + return 1; 1.523 + } 1.524 + if( args[i].equals("-npa")) { 1.525 + packageLevelAnnotations = false; 1.526 + return 1; 1.527 + } 1.528 + if( args[i].equals("-no-header")) { 1.529 + noFileHeader = true; 1.530 + return 1; 1.531 + } 1.532 + if (args[i].equals("-verbose")) { 1.533 + verbose = true; 1.534 + return 1; 1.535 + } 1.536 + if (args[i].equals("-quiet")) { 1.537 + quiet = true; 1.538 + return 1; 1.539 + } 1.540 + if (args[i].equals("-XexplicitAnnotation")) { 1.541 + runtime14 = true; 1.542 + return 1; 1.543 + } 1.544 + if (args[i].equals("-enableIntrospection")) { 1.545 + enableIntrospection = true; 1.546 + return 1; 1.547 + } 1.548 + if (args[i].equals("-contentForWildcard")) { 1.549 + contentForWildcard = true; 1.550 + return 1; 1.551 + } 1.552 + if (args[i].equals("-XautoNameResolution")) { 1.553 + automaticNameConflictResolution = true; 1.554 + return 1; 1.555 + } 1.556 + if (args[i].equals("-b")) { 1.557 + addFile(requireArgument("-b",args,++i),bindFiles,".xjb"); 1.558 + return 2; 1.559 + } 1.560 + if (args[i].equals("-dtd")) { 1.561 + schemaLanguage = Language.DTD; 1.562 + return 1; 1.563 + } 1.564 + if (args[i].equals("-relaxng")) { 1.565 + schemaLanguage = Language.RELAXNG; 1.566 + return 1; 1.567 + } 1.568 + if (args[i].equals("-relaxng-compact")) { 1.569 + schemaLanguage = Language.RELAXNG_COMPACT; 1.570 + return 1; 1.571 + } 1.572 + if (args[i].equals("-xmlschema")) { 1.573 + schemaLanguage = Language.XMLSCHEMA; 1.574 + return 1; 1.575 + } 1.576 + if (args[i].equals("-wsdl")) { 1.577 + schemaLanguage = Language.WSDL; 1.578 + return 1; 1.579 + } 1.580 + if (args[i].equals("-extension")) { 1.581 + compatibilityMode = EXTENSION; 1.582 + return 1; 1.583 + } 1.584 + if (args[i].equals("-target")) { 1.585 + String token = requireArgument("-target",args,++i); 1.586 + target = SpecVersion.parse(token); 1.587 + if(target==null) 1.588 + throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_TARGET_VERSION,token)); 1.589 + return 2; 1.590 + } 1.591 + if (args[i].equals("-httpproxyfile")) { 1.592 + if (i == args.length - 1 || args[i + 1].startsWith("-")) { 1.593 + throw new BadCommandLineException( 1.594 + Messages.format(Messages.MISSING_PROXYFILE)); 1.595 + } 1.596 + 1.597 + File file = new File(args[++i]); 1.598 + if(!file.exists()) { 1.599 + throw new BadCommandLineException( 1.600 + Messages.format(Messages.NO_SUCH_FILE,file)); 1.601 + } 1.602 + 1.603 + try { 1.604 + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8")); 1.605 + parseProxy(in.readLine()); 1.606 + in.close(); 1.607 + } catch (IOException e) { 1.608 + throw new BadCommandLineException( 1.609 + Messages.format(Messages.FAILED_TO_PARSE,file,e.getMessage()),e); 1.610 + } 1.611 + 1.612 + return 2; 1.613 + } 1.614 + if (args[i].equals("-httpproxy")) { 1.615 + if (i == args.length - 1 || args[i + 1].startsWith("-")) { 1.616 + throw new BadCommandLineException( 1.617 + Messages.format(Messages.MISSING_PROXY)); 1.618 + } 1.619 + 1.620 + parseProxy(args[++i]); 1.621 + return 2; 1.622 + } 1.623 + if (args[i].equals("-host")) { 1.624 + proxyHost = requireArgument("-host",args,++i); 1.625 + return 2; 1.626 + } 1.627 + if (args[i].equals("-port")) { 1.628 + proxyPort = requireArgument("-port",args,++i); 1.629 + return 2; 1.630 + } 1.631 + if( args[i].equals("-catalog") ) { 1.632 + // use Sun's "XML Entity and URI Resolvers" by Norman Walsh 1.633 + // to resolve external entities. 1.634 + // http://www.sun.com/xml/developers/resolver/ 1.635 + 1.636 + File catalogFile = new File(requireArgument("-catalog",args,++i)); 1.637 + try { 1.638 + addCatalog(catalogFile); 1.639 + } catch (IOException e) { 1.640 + throw new BadCommandLineException( 1.641 + Messages.format(Messages.FAILED_TO_PARSE,catalogFile,e.getMessage()),e); 1.642 + } 1.643 + return 2; 1.644 + } 1.645 + if (args[i].equals("-source")) { 1.646 + String version = requireArgument("-source",args,++i); 1.647 + //For source 1.0 the 1.0 Driver is loaded 1.648 + //Hence anything other than 2.0 is defaulted to 1.649 + //2.0 1.650 + if( !version.equals("2.0") && !version.equals("2.1") ) 1.651 + throw new BadCommandLineException( 1.652 + Messages.format(Messages.DEFAULT_VERSION)); 1.653 + return 2; 1.654 + } 1.655 + if( args[i].equals("-Xtest-class-name-allocator") ) { 1.656 + classNameAllocator = new ClassNameAllocator() { 1.657 + public String assignClassName(String packageName, String className) { 1.658 + System.out.printf("assignClassName(%s,%s)\n",packageName,className); 1.659 + return className+"_Type"; 1.660 + } 1.661 + }; 1.662 + return 1; 1.663 + } 1.664 + 1.665 + if (args[i].equals("-encoding")) { 1.666 + encoding = requireArgument("-encoding", args, ++i); 1.667 + try { 1.668 + if (!Charset.isSupported(encoding)) { 1.669 + throw new BadCommandLineException( 1.670 + Messages.format(Messages.UNSUPPORTED_ENCODING, encoding)); 1.671 + } 1.672 + } catch (IllegalCharsetNameException icne) { 1.673 + throw new BadCommandLineException( 1.674 + Messages.format(Messages.UNSUPPORTED_ENCODING, encoding)); 1.675 + } 1.676 + return 2; 1.677 + } 1.678 + 1.679 + // see if this is one of the extensions 1.680 + for( Plugin plugin : getAllPlugins() ) { 1.681 + try { 1.682 + if( ('-'+plugin.getOptionName()).equals(args[i]) ) { 1.683 + activePlugins.add(plugin); 1.684 + plugin.onActivated(this); 1.685 + pluginURIs.addAll(plugin.getCustomizationURIs()); 1.686 + 1.687 + // give the plugin a chance to parse arguments to this option. 1.688 + // this is new in 2.1, and due to the backward compatibility reason, 1.689 + // if plugin didn't understand it, we still return 1 to indicate 1.690 + // that this option is consumed. 1.691 + int r = plugin.parseArgument(this,args,i); 1.692 + if(r!=0) 1.693 + return r; 1.694 + else 1.695 + return 1; 1.696 + } 1.697 + 1.698 + int r = plugin.parseArgument(this,args,i); 1.699 + if(r!=0) return r; 1.700 + } catch (IOException e) { 1.701 + throw new BadCommandLineException(e.getMessage(),e); 1.702 + } 1.703 + } 1.704 + 1.705 + return 0; // unrecognized 1.706 + } 1.707 + 1.708 + private void parseProxy(String text) throws BadCommandLineException { 1.709 + // syntax is [user[:password]@]proxyHost:proxyPort 1.710 + String token = "([^@:]+)"; 1.711 + Pattern p = Pattern.compile("(?:"+token+"(?:\\:"+token+")?\\@)?"+token+"(?:\\:"+token+")"); 1.712 + 1.713 + Matcher matcher = p.matcher(text); 1.714 + if(!matcher.matches()) 1.715 + throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_PROXY,text)); 1.716 + 1.717 + proxyUser = matcher.group(1); 1.718 + proxyPassword = matcher.group(2); 1.719 + proxyHost = matcher.group(3); 1.720 + proxyPort = matcher.group(4); 1.721 + try { 1.722 + Integer.valueOf(proxyPort); 1.723 + } catch (NumberFormatException e) { 1.724 + throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_PROXY,text)); 1.725 + } 1.726 + } 1.727 + 1.728 + /** 1.729 + * Obtains an operand and reports an error if it's not there. 1.730 + */ 1.731 + public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException { 1.732 + if (i == args.length || args[i].startsWith("-")) { 1.733 + throw new BadCommandLineException( 1.734 + Messages.format(Messages.MISSING_OPERAND,optionName)); 1.735 + } 1.736 + return args[i]; 1.737 + } 1.738 + 1.739 + /** 1.740 + * Parses a token to a file (or a set of files) 1.741 + * and add them as {@link InputSource} to the specified list. 1.742 + * 1.743 + * @param suffix 1.744 + * If the given token is a directory name, we do a recusive search 1.745 + * and find all files that have the given suffix. 1.746 + */ 1.747 + private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException { 1.748 + Object src; 1.749 + try { 1.750 + src = Util.getFileOrURL(name); 1.751 + } catch (IOException e) { 1.752 + throw new BadCommandLineException( 1.753 + Messages.format(Messages.NOT_A_FILE_NOR_URL,name)); 1.754 + } 1.755 + if(src instanceof URL) { 1.756 + target.add(absolutize(new InputSource(Util.escapeSpace(((URL)src).toExternalForm())))); 1.757 + } else { 1.758 + File fsrc = (File)src; 1.759 + if(fsrc.isDirectory()) { 1.760 + addRecursive(fsrc,suffix,target); 1.761 + } else { 1.762 + target.add(absolutize(fileToInputSource(fsrc))); 1.763 + } 1.764 + } 1.765 + } 1.766 + 1.767 + /** 1.768 + * Adds a new catalog file. 1.769 + */ 1.770 + public void addCatalog(File catalogFile) throws IOException { 1.771 + if(entityResolver==null) { 1.772 + CatalogManager.getStaticManager().setIgnoreMissingProperties(true); 1.773 + entityResolver = new CatalogResolver(true); 1.774 + } 1.775 + ((CatalogResolver)entityResolver).getCatalog().parseCatalog(catalogFile.getPath()); 1.776 + } 1.777 + 1.778 + /** 1.779 + * Parses arguments and fill fields of this object. 1.780 + * 1.781 + * @exception BadCommandLineException 1.782 + * thrown when there's a problem in the command-line arguments 1.783 + */ 1.784 + public void parseArguments( String[] args ) throws BadCommandLineException { 1.785 + 1.786 + for (int i = 0; i < args.length; i++) { 1.787 + if(args[i].length()==0) 1.788 + throw new BadCommandLineException(); 1.789 + if (args[i].charAt(0) == '-') { 1.790 + int j = parseArgument(args,i); 1.791 + if(j==0) 1.792 + throw new BadCommandLineException( 1.793 + Messages.format(Messages.UNRECOGNIZED_PARAMETER, args[i])); 1.794 + i += (j-1); 1.795 + } else { 1.796 + if(args[i].endsWith(".jar")) 1.797 + scanEpisodeFile(new File(args[i])); 1.798 + else 1.799 + addFile(args[i],grammars,".xsd"); 1.800 + } 1.801 + } 1.802 + 1.803 + // configure proxy 1.804 + if (proxyHost != null || proxyPort != null) { 1.805 + if (proxyHost != null && proxyPort != null) { 1.806 + System.setProperty("http.proxyHost", proxyHost); 1.807 + System.setProperty("http.proxyPort", proxyPort); 1.808 + System.setProperty("https.proxyHost", proxyHost); 1.809 + System.setProperty("https.proxyPort", proxyPort); 1.810 + } else if (proxyHost == null) { 1.811 + throw new BadCommandLineException( 1.812 + Messages.format(Messages.MISSING_PROXYHOST)); 1.813 + } else { 1.814 + throw new BadCommandLineException( 1.815 + Messages.format(Messages.MISSING_PROXYPORT)); 1.816 + } 1.817 + if(proxyUser!=null) 1.818 + System.setProperty("http.proxyUser", proxyUser); 1.819 + if(proxyPassword!=null) 1.820 + System.setProperty("http.proxyPassword", proxyPassword); 1.821 + 1.822 + } 1.823 + 1.824 + if (grammars.isEmpty()) 1.825 + throw new BadCommandLineException( 1.826 + Messages.format(Messages.MISSING_GRAMMAR)); 1.827 + 1.828 + if( schemaLanguage==null ) 1.829 + schemaLanguage = guessSchemaLanguage(); 1.830 + 1.831 +// if(target==SpecVersion.V2_2 && !isExtensionMode()) 1.832 +// throw new BadCommandLineException( 1.833 +// "Currently 2.2 is still not finalized yet, so using it requires the -extension switch." + 1.834 +// "NOTE THAT 2.2 SPEC MAY CHANGE BEFORE IT BECOMES FINAL."); 1.835 + 1.836 + if(pluginLoadFailure!=null) 1.837 + throw new BadCommandLineException( 1.838 + Messages.format(Messages.PLUGIN_LOAD_FAILURE,pluginLoadFailure)); 1.839 + } 1.840 + 1.841 + /** 1.842 + * Finds the <tt>META-INF/sun-jaxb.episode</tt> file to add as a binding customization. 1.843 + */ 1.844 + public void scanEpisodeFile(File jar) throws BadCommandLineException { 1.845 + try { 1.846 + URLClassLoader ucl = new URLClassLoader(new URL[]{jar.toURL()}); 1.847 + Enumeration<URL> resources = ucl.findResources("META-INF/sun-jaxb.episode"); 1.848 + while (resources.hasMoreElements()) { 1.849 + URL url = resources.nextElement(); 1.850 + addBindFile(new InputSource(url.toExternalForm())); 1.851 + } 1.852 + } catch (IOException e) { 1.853 + throw new BadCommandLineException( 1.854 + Messages.format(Messages.FAILED_TO_LOAD,jar,e.getMessage()), e); 1.855 + } 1.856 + } 1.857 + 1.858 + 1.859 + /** 1.860 + * Guesses the schema language. 1.861 + */ 1.862 + public Language guessSchemaLanguage() { 1.863 + 1.864 + // otherwise, use the file extension. 1.865 + // not a good solution, but very easy. 1.866 + if ((grammars != null) && (grammars.size() > 0)) { 1.867 + String name = grammars.get(0).getSystemId().toLowerCase(); 1.868 + 1.869 + if (name.endsWith(".rng")) 1.870 + return Language.RELAXNG; 1.871 + if (name.endsWith(".rnc")) 1.872 + return Language.RELAXNG_COMPACT; 1.873 + if (name.endsWith(".dtd")) 1.874 + return Language.DTD; 1.875 + if (name.endsWith(".wsdl")) 1.876 + return Language.WSDL; 1.877 + } 1.878 + 1.879 + // by default, assume XML Schema 1.880 + return Language.XMLSCHEMA; 1.881 + } 1.882 + 1.883 + /** 1.884 + * Creates a configured CodeWriter that produces files into the specified directory. 1.885 + */ 1.886 + public CodeWriter createCodeWriter() throws IOException { 1.887 + return createCodeWriter(new FileCodeWriter( targetDir, readOnly, encoding )); 1.888 + } 1.889 + 1.890 + /** 1.891 + * Creates a configured CodeWriter that produces files into the specified directory. 1.892 + */ 1.893 + public CodeWriter createCodeWriter( CodeWriter core ) { 1.894 + if(noFileHeader) 1.895 + return core; 1.896 + 1.897 + return new PrologCodeWriter( core,getPrologComment() ); 1.898 + } 1.899 + 1.900 + /** 1.901 + * Gets the string suitable to be used as the prolog comment baked into artifacts. 1.902 + * This is the string like "This file was generated by the JAXB RI on YYYY/mm/dd..." 1.903 + */ 1.904 + public String getPrologComment() { 1.905 + // generate format syntax: <date> 'at' <time> 1.906 + String format = 1.907 + Messages.format(Messages.DATE_FORMAT) 1.908 + + " '" 1.909 + + Messages.format(Messages.AT) 1.910 + + "' " 1.911 + + Messages.format(Messages.TIME_FORMAT); 1.912 + SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.ENGLISH); 1.913 + 1.914 + return Messages.format( 1.915 + Messages.FILE_PROLOG_COMMENT, 1.916 + dateFormat.format(new Date())); 1.917 + } 1.918 + 1.919 + /** 1.920 + * If a plugin failed to load, report. 1.921 + */ 1.922 + private static String pluginLoadFailure; 1.923 + 1.924 + /** 1.925 + * Looks for all "META-INF/services/[className]" files and 1.926 + * create one instance for each class name found inside this file. 1.927 + */ 1.928 + private static <T> T[] findServices( Class<T> clazz, ClassLoader classLoader ) { 1.929 + // if true, print debug output 1.930 + final boolean debug = com.sun.tools.internal.xjc.util.Util.getSystemProperty(Options.class,"findServices")!=null; 1.931 + 1.932 + // if we are running on Mustang or Dolphin, use ServiceLoader 1.933 + // so that we can take advantage of JSR-277 module system. 1.934 + try { 1.935 + Class<?> serviceLoader = Class.forName("java.util.ServiceLoader"); 1.936 + if(debug) 1.937 + System.out.println("Using java.util.ServiceLoader"); 1.938 + Iterable<T> itr = (Iterable<T>)serviceLoader.getMethod("load",Class.class,ClassLoader.class).invoke(null,clazz,classLoader); 1.939 + List<T> r = new ArrayList<T>(); 1.940 + for (T t : itr) 1.941 + r.add(t); 1.942 + return r.toArray((T[])Array.newInstance(clazz,r.size())); 1.943 + } catch (ClassNotFoundException e) { 1.944 + // fall through 1.945 + } catch (IllegalAccessException e) { 1.946 + Error x = new IllegalAccessError(); 1.947 + x.initCause(e); 1.948 + throw x; 1.949 + } catch (InvocationTargetException e) { 1.950 + Throwable x = e.getTargetException(); 1.951 + if (x instanceof RuntimeException) 1.952 + throw (RuntimeException) x; 1.953 + if (x instanceof Error) 1.954 + throw (Error) x; 1.955 + throw new Error(x); 1.956 + } catch (NoSuchMethodException e) { 1.957 + Error x = new NoSuchMethodError(); 1.958 + x.initCause(e); 1.959 + throw x; 1.960 + } 1.961 + 1.962 + String serviceId = "META-INF/services/" + clazz.getName(); 1.963 + 1.964 + // used to avoid creating the same instance twice 1.965 + Set<String> classNames = new HashSet<String>(); 1.966 + 1.967 + if(debug) { 1.968 + System.out.println("Looking for "+serviceId+" for add-ons"); 1.969 + } 1.970 + 1.971 + // try to find services in CLASSPATH 1.972 + try { 1.973 + Enumeration<URL> e = classLoader.getResources(serviceId); 1.974 + if(e==null) return (T[])Array.newInstance(clazz,0); 1.975 + 1.976 + ArrayList<T> a = new ArrayList<T>(); 1.977 + while(e.hasMoreElements()) { 1.978 + URL url = e.nextElement(); 1.979 + BufferedReader reader=null; 1.980 + 1.981 + if(debug) { 1.982 + System.out.println("Checking "+url+" for an add-on"); 1.983 + } 1.984 + 1.985 + try { 1.986 + reader = new BufferedReader(new InputStreamReader(url.openStream())); 1.987 + String impl; 1.988 + while((impl = reader.readLine())!=null ) { 1.989 + // try to instanciate the object 1.990 + impl = impl.trim(); 1.991 + if(classNames.add(impl)) { 1.992 + Class implClass = classLoader.loadClass(impl); 1.993 + if(!clazz.isAssignableFrom(implClass)) { 1.994 + pluginLoadFailure = impl+" is not a subclass of "+clazz+". Skipping"; 1.995 + if(debug) 1.996 + System.out.println(pluginLoadFailure); 1.997 + continue; 1.998 + } 1.999 + if(debug) { 1.1000 + System.out.println("Attempting to instanciate "+impl); 1.1001 + } 1.1002 + a.add(clazz.cast(implClass.newInstance())); 1.1003 + } 1.1004 + } 1.1005 + reader.close(); 1.1006 + } catch( Exception ex ) { 1.1007 + // let it go. 1.1008 + StringWriter w = new StringWriter(); 1.1009 + ex.printStackTrace(new PrintWriter(w)); 1.1010 + pluginLoadFailure = w.toString(); 1.1011 + if(debug) { 1.1012 + System.out.println(pluginLoadFailure); 1.1013 + } 1.1014 + if( reader!=null ) { 1.1015 + try { 1.1016 + reader.close(); 1.1017 + } catch( IOException ex2 ) { 1.1018 + // ignore 1.1019 + } 1.1020 + } 1.1021 + } 1.1022 + } 1.1023 + 1.1024 + return a.toArray((T[])Array.newInstance(clazz,a.size())); 1.1025 + } catch( Throwable e ) { 1.1026 + // ignore any error 1.1027 + StringWriter w = new StringWriter(); 1.1028 + e.printStackTrace(new PrintWriter(w)); 1.1029 + pluginLoadFailure = w.toString(); 1.1030 + if(debug) { 1.1031 + System.out.println(pluginLoadFailure); 1.1032 + } 1.1033 + return (T[])Array.newInstance(clazz,0); 1.1034 + } 1.1035 + } 1.1036 + 1.1037 + // this is a convenient place to expose the build version to xjc plugins 1.1038 + public static String getBuildID() { 1.1039 + return Messages.format(Messages.BUILD_ID); 1.1040 + } 1.1041 + 1.1042 + public static String normalizeSystemId(String systemId) { 1.1043 + try { 1.1044 + systemId = new URI(systemId).normalize().toString(); 1.1045 + } catch (URISyntaxException e) { 1.1046 + // leave the system ID untouched. In my experience URI is often too strict 1.1047 + } 1.1048 + return systemId; 1.1049 + } 1.1050 + 1.1051 +}