src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.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.BufferedReader;
aoqi@0 29 import java.io.File;
aoqi@0 30 import java.io.FileInputStream;
aoqi@0 31 import java.io.IOException;
aoqi@0 32 import java.io.InputStreamReader;
aoqi@0 33 import java.io.PrintWriter;
aoqi@0 34 import java.io.StringWriter;
aoqi@0 35 import java.lang.reflect.Array;
aoqi@0 36 import java.lang.reflect.InvocationTargetException;
aoqi@0 37 import java.net.MalformedURLException;
aoqi@0 38 import java.net.URL;
aoqi@0 39 import java.net.URLClassLoader;
aoqi@0 40 import java.text.SimpleDateFormat;
aoqi@0 41 import java.util.ArrayList;
aoqi@0 42 import java.util.Arrays;
aoqi@0 43 import java.util.Date;
aoqi@0 44 import java.util.Enumeration;
aoqi@0 45 import java.util.HashSet;
aoqi@0 46 import java.util.List;
aoqi@0 47 import java.util.Set;
aoqi@0 48
aoqi@0 49 import com.sun.codemodel.internal.CodeWriter;
aoqi@0 50 import com.sun.codemodel.internal.JPackage;
aoqi@0 51 import com.sun.codemodel.internal.JResourceFile;
aoqi@0 52 import com.sun.codemodel.internal.writer.FileCodeWriter;
aoqi@0 53 import com.sun.codemodel.internal.writer.PrologCodeWriter;
aoqi@0 54 import com.sun.istack.internal.tools.DefaultAuthenticator;
aoqi@0 55 import com.sun.org.apache.xml.internal.resolver.CatalogManager;
aoqi@0 56 import com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver;
aoqi@0 57 import com.sun.tools.internal.xjc.api.ClassNameAllocator;
aoqi@0 58 import com.sun.tools.internal.xjc.api.SpecVersion;
aoqi@0 59 import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
aoqi@0 60 import com.sun.tools.internal.xjc.model.Model;
aoqi@0 61 import com.sun.tools.internal.xjc.reader.Util;
aoqi@0 62 import com.sun.xml.internal.bind.api.impl.NameConverter;
aoqi@0 63 import java.net.URI;
aoqi@0 64 import java.net.URISyntaxException;
aoqi@0 65 import java.nio.charset.Charset;
aoqi@0 66 import java.nio.charset.IllegalCharsetNameException;
aoqi@0 67 import java.util.Locale;
aoqi@0 68 import java.util.logging.Level;
aoqi@0 69 import java.util.logging.Logger;
aoqi@0 70
aoqi@0 71 import org.xml.sax.EntityResolver;
aoqi@0 72 import org.xml.sax.InputSource;
aoqi@0 73
aoqi@0 74 /**
aoqi@0 75 * Global options.
aoqi@0 76 *
aoqi@0 77 * <p>
aoqi@0 78 * This class stores invocation configuration for XJC.
aoqi@0 79 * The configuration in this class should be abstract enough so that
aoqi@0 80 * it could be parsed from both command-line or Ant.
aoqi@0 81 */
aoqi@0 82 public class Options
aoqi@0 83 {
aoqi@0 84 /** If "-debug" is specified. */
aoqi@0 85 public boolean debugMode;
aoqi@0 86
aoqi@0 87 /** If the "-verbose" option is specified. */
aoqi@0 88 public boolean verbose;
aoqi@0 89
aoqi@0 90 /** If the "-quiet" option is specified. */
aoqi@0 91 public boolean quiet;
aoqi@0 92
aoqi@0 93 /** If the -readOnly option is specified. */
aoqi@0 94 public boolean readOnly;
aoqi@0 95
aoqi@0 96 /** No file header comment (to be more friendly with diff.) */
aoqi@0 97 public boolean noFileHeader;
aoqi@0 98
aoqi@0 99 /** When on, fixes getter/setter generation to match the Bean Introspection API */
aoqi@0 100 public boolean enableIntrospection;
aoqi@0 101
aoqi@0 102 /** When on, generates content property for types with multiple xs:any derived elements (which is supposed to be correct behaviour) */
aoqi@0 103 public boolean contentForWildcard;
aoqi@0 104
aoqi@0 105 /** Encoding to be used by generated java sources, null for platform default. */
aoqi@0 106 public String encoding;
aoqi@0 107
aoqi@0 108 /**
aoqi@0 109 * If true XML security features when parsing XML documents will be disabled.
aoqi@0 110 * The default value is false.
aoqi@0 111 *
aoqi@0 112 * Boolean
aoqi@0 113 * @since 2.2.6
aoqi@0 114 */
aoqi@0 115 public boolean disableXmlSecurity;
aoqi@0 116
aoqi@0 117 /**
aoqi@0 118 * Check the source schemas with extra scrutiny.
aoqi@0 119 * The exact meaning depends on the schema language.
aoqi@0 120 */
aoqi@0 121 public boolean strictCheck =true;
aoqi@0 122
aoqi@0 123 /**
aoqi@0 124 * If -explicit-annotation option is specified.
aoqi@0 125 * <p>
aoqi@0 126 * This generates code that works around issues specific to 1.4 runtime.
aoqi@0 127 */
aoqi@0 128 public boolean runtime14 = false;
aoqi@0 129
aoqi@0 130 /**
aoqi@0 131 * If true, try to resolve name conflicts automatically by assigning mechanical numbers.
aoqi@0 132 */
aoqi@0 133 public boolean automaticNameConflictResolution = false;
aoqi@0 134
aoqi@0 135 /**
aoqi@0 136 * strictly follow the compatibility rules and reject schemas that
aoqi@0 137 * contain features from App. E.2, use vendor binding extensions
aoqi@0 138 */
aoqi@0 139 public static final int STRICT = 1;
aoqi@0 140 /**
aoqi@0 141 * loosely follow the compatibility rules and allow the use of vendor
aoqi@0 142 * binding extensions
aoqi@0 143 */
aoqi@0 144 public static final int EXTENSION = 2;
aoqi@0 145
aoqi@0 146 /**
aoqi@0 147 * this switch determines how carefully the compiler will follow
aoqi@0 148 * the compatibility rules in the spec. Either <code>STRICT</code>
aoqi@0 149 * or <code>EXTENSION</code>.
aoqi@0 150 */
aoqi@0 151 public int compatibilityMode = STRICT;
aoqi@0 152
aoqi@0 153 public boolean isExtensionMode() {
aoqi@0 154 return compatibilityMode==EXTENSION;
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 private static final Logger logger = com.sun.xml.internal.bind.Util.getClassLogger();
aoqi@0 158
aoqi@0 159 /**
aoqi@0 160 * Generates output for the specified version of the runtime.
aoqi@0 161 */
aoqi@0 162 public SpecVersion target = SpecVersion.LATEST;
aoqi@0 163
aoqi@0 164
aoqi@0 165 public Options() {
aoqi@0 166 try {
aoqi@0 167 Class.forName("javax.xml.bind.JAXBPermission");
aoqi@0 168 } catch (ClassNotFoundException cnfe) {
aoqi@0 169 target = SpecVersion.V2_1;
aoqi@0 170 }
aoqi@0 171 }
aoqi@0 172
aoqi@0 173 /**
aoqi@0 174 * Target directory when producing files.
aoqi@0 175 * <p>
aoqi@0 176 * This field is not used when XJC is driven through the XJC API.
aoqi@0 177 * Plugins that need to generate extra files should do so by using
aoqi@0 178 * {@link JPackage#addResourceFile(JResourceFile)}.
aoqi@0 179 */
aoqi@0 180 public File targetDir = new File(".");
aoqi@0 181
aoqi@0 182 /**
aoqi@0 183 * Actually stores {@link CatalogResolver}, but the field
aoqi@0 184 * type is made to {@link EntityResolver} so that XJC can be
aoqi@0 185 * used even if resolver.jar is not available in the classpath.
aoqi@0 186 */
aoqi@0 187 public EntityResolver entityResolver = null;
aoqi@0 188
aoqi@0 189 /**
aoqi@0 190 * Type of input schema language. One of the <code>SCHEMA_XXX</code>
aoqi@0 191 * constants.
aoqi@0 192 */
aoqi@0 193 private Language schemaLanguage = null;
aoqi@0 194
aoqi@0 195 /**
aoqi@0 196 * The -p option that should control the default Java package that
aoqi@0 197 * will contain the generated code. Null if unspecified.
aoqi@0 198 */
aoqi@0 199 public String defaultPackage = null;
aoqi@0 200
aoqi@0 201 /**
aoqi@0 202 * Similar to the -p option, but this one works with a lower priority,
aoqi@0 203 * and customizations overrides this. Used by JAX-RPC.
aoqi@0 204 */
aoqi@0 205 public String defaultPackage2 = null;
aoqi@0 206
aoqi@0 207 /**
aoqi@0 208 * Input schema files as a list of {@link InputSource}s.
aoqi@0 209 */
aoqi@0 210 private final List<InputSource> grammars = new ArrayList<InputSource>();
aoqi@0 211
aoqi@0 212 private final List<InputSource> bindFiles = new ArrayList<InputSource>();
aoqi@0 213
aoqi@0 214 // Proxy setting.
aoqi@0 215 private String proxyHost = null;
aoqi@0 216 private String proxyPort = null;
aoqi@0 217 public String proxyAuth = null;
aoqi@0 218
aoqi@0 219 /**
aoqi@0 220 * {@link Plugin}s that are enabled in this compilation.
aoqi@0 221 */
aoqi@0 222 public final List<Plugin> activePlugins = new ArrayList<Plugin>();
aoqi@0 223
aoqi@0 224 /**
aoqi@0 225 * All discovered {@link Plugin}s.
aoqi@0 226 * This is lazily parsed, so that we can take '-cp' option into account.
aoqi@0 227 *
aoqi@0 228 * @see #getAllPlugins()
aoqi@0 229 */
aoqi@0 230 private List<Plugin> allPlugins;
aoqi@0 231
aoqi@0 232 /**
aoqi@0 233 * Set of URIs that plug-ins recognize as extension bindings.
aoqi@0 234 */
aoqi@0 235 public final Set<String> pluginURIs = new HashSet<String>();
aoqi@0 236
aoqi@0 237 /**
aoqi@0 238 * This allocator has the final say on deciding the class name.
aoqi@0 239 */
aoqi@0 240 public ClassNameAllocator classNameAllocator;
aoqi@0 241
aoqi@0 242 /**
aoqi@0 243 * This switch controls whether or not xjc will generate package level annotations
aoqi@0 244 */
aoqi@0 245 public boolean packageLevelAnnotations = true;
aoqi@0 246
aoqi@0 247 /**
aoqi@0 248 * This {@link FieldRendererFactory} determines how the fields are generated.
aoqi@0 249 */
aoqi@0 250 private FieldRendererFactory fieldRendererFactory = new FieldRendererFactory();
aoqi@0 251 /**
aoqi@0 252 * Used to detect if two {@link Plugin}s try to overwrite {@link #fieldRendererFactory}.
aoqi@0 253 */
aoqi@0 254 private Plugin fieldRendererFactoryOwner = null;
aoqi@0 255
aoqi@0 256 /**
aoqi@0 257 * If this is non-null, we use this {@link NameConverter} over the one
aoqi@0 258 * given in the schema/binding.
aoqi@0 259 */
aoqi@0 260 private NameConverter nameConverter = null;
aoqi@0 261 /**
aoqi@0 262 * Used to detect if two {@link Plugin}s try to overwrite {@link #nameConverter}.
aoqi@0 263 */
aoqi@0 264 private Plugin nameConverterOwner = null;
aoqi@0 265
aoqi@0 266 /**
aoqi@0 267 * Gets the active {@link FieldRendererFactory} that shall be used to build {@link Model}.
aoqi@0 268 *
aoqi@0 269 * @return always non-null.
aoqi@0 270 */
aoqi@0 271 public FieldRendererFactory getFieldRendererFactory() {
aoqi@0 272 return fieldRendererFactory;
aoqi@0 273 }
aoqi@0 274
aoqi@0 275 /**
aoqi@0 276 * Sets the {@link FieldRendererFactory}.
aoqi@0 277 *
aoqi@0 278 * <p>
aoqi@0 279 * This method is for plugins to call to set a custom {@link FieldRendererFactory}.
aoqi@0 280 *
aoqi@0 281 * @param frf
aoqi@0 282 * The {@link FieldRendererFactory} to be installed. Must not be null.
aoqi@0 283 * @param owner
aoqi@0 284 * Identifies the plugin that owns this {@link FieldRendererFactory}.
aoqi@0 285 * When two {@link Plugin}s try to call this method, this allows XJC
aoqi@0 286 * to report it as a user-friendly error message.
aoqi@0 287 *
aoqi@0 288 * @throws BadCommandLineException
aoqi@0 289 * If a conflit happens, this exception carries a user-friendly error
aoqi@0 290 * message, indicating a conflict.
aoqi@0 291 */
aoqi@0 292 public void setFieldRendererFactory(FieldRendererFactory frf, Plugin owner) throws BadCommandLineException {
aoqi@0 293 // since this method is for plugins, make it bit more fool-proof than usual
aoqi@0 294 if(frf==null)
aoqi@0 295 throw new IllegalArgumentException();
aoqi@0 296 if(fieldRendererFactoryOwner!=null) {
aoqi@0 297 throw new BadCommandLineException(
aoqi@0 298 Messages.format(Messages.FIELD_RENDERER_CONFLICT,
aoqi@0 299 fieldRendererFactoryOwner.getOptionName(),
aoqi@0 300 owner.getOptionName() ));
aoqi@0 301 }
aoqi@0 302 this.fieldRendererFactoryOwner = owner;
aoqi@0 303 this.fieldRendererFactory = frf;
aoqi@0 304 }
aoqi@0 305
aoqi@0 306
aoqi@0 307 /**
aoqi@0 308 * Gets the active {@link NameConverter} that shall be used to build {@link Model}.
aoqi@0 309 *
aoqi@0 310 * @return can be null, in which case it's up to the binding.
aoqi@0 311 */
aoqi@0 312 public NameConverter getNameConverter() {
aoqi@0 313 return nameConverter;
aoqi@0 314 }
aoqi@0 315
aoqi@0 316 /**
aoqi@0 317 * Sets the {@link NameConverter}.
aoqi@0 318 *
aoqi@0 319 * <p>
aoqi@0 320 * This method is for plugins to call to set a custom {@link NameConverter}.
aoqi@0 321 *
aoqi@0 322 * @param nc
aoqi@0 323 * The {@link NameConverter} to be installed. Must not be null.
aoqi@0 324 * @param owner
aoqi@0 325 * Identifies the plugin that owns this {@link NameConverter}.
aoqi@0 326 * When two {@link Plugin}s try to call this method, this allows XJC
aoqi@0 327 * to report it as a user-friendly error message.
aoqi@0 328 *
aoqi@0 329 * @throws BadCommandLineException
aoqi@0 330 * If a conflit happens, this exception carries a user-friendly error
aoqi@0 331 * message, indicating a conflict.
aoqi@0 332 */
aoqi@0 333 public void setNameConverter(NameConverter nc, Plugin owner) throws BadCommandLineException {
aoqi@0 334 // since this method is for plugins, make it bit more fool-proof than usual
aoqi@0 335 if(nc==null)
aoqi@0 336 throw new IllegalArgumentException();
aoqi@0 337 if(nameConverter!=null) {
aoqi@0 338 throw new BadCommandLineException(
aoqi@0 339 Messages.format(Messages.NAME_CONVERTER_CONFLICT,
aoqi@0 340 nameConverterOwner.getOptionName(),
aoqi@0 341 owner.getOptionName() ));
aoqi@0 342 }
aoqi@0 343 this.nameConverterOwner = owner;
aoqi@0 344 this.nameConverter = nc;
aoqi@0 345 }
aoqi@0 346
aoqi@0 347 /**
aoqi@0 348 * Gets all the {@link Plugin}s discovered so far.
aoqi@0 349 *
aoqi@0 350 * <p>
aoqi@0 351 * A plugins are enumerated when this method is called for the first time,
aoqi@0 352 * by taking {@link #classpaths} into account. That means
aoqi@0 353 * "-cp plugin.jar" has to come before you specify options to enable it.
aoqi@0 354 */
aoqi@0 355 public List<Plugin> getAllPlugins() {
aoqi@0 356 if(allPlugins==null) {
aoqi@0 357 allPlugins = new ArrayList<Plugin>();
aoqi@0 358 ClassLoader ucl = getUserClassLoader(SecureLoader.getClassClassLoader(getClass()));
aoqi@0 359 allPlugins.addAll(Arrays.asList(findServices(Plugin.class,ucl)));
aoqi@0 360 }
aoqi@0 361
aoqi@0 362 return allPlugins;
aoqi@0 363 }
aoqi@0 364
aoqi@0 365 public Language getSchemaLanguage() {
aoqi@0 366 if( schemaLanguage==null)
aoqi@0 367 schemaLanguage = guessSchemaLanguage();
aoqi@0 368 return schemaLanguage;
aoqi@0 369 }
aoqi@0 370 public void setSchemaLanguage(Language _schemaLanguage) {
aoqi@0 371 this.schemaLanguage = _schemaLanguage;
aoqi@0 372 }
aoqi@0 373
aoqi@0 374 /** Input schema files. */
aoqi@0 375 public InputSource[] getGrammars() {
aoqi@0 376 return grammars.toArray(new InputSource[grammars.size()]);
aoqi@0 377 }
aoqi@0 378
aoqi@0 379 /**
aoqi@0 380 * Adds a new input schema.
aoqi@0 381 */
aoqi@0 382 public void addGrammar( InputSource is ) {
aoqi@0 383 grammars.add(absolutize(is));
aoqi@0 384 }
aoqi@0 385
aoqi@0 386 private InputSource fileToInputSource( File source ) {
aoqi@0 387 try {
aoqi@0 388 String url = source.toURL().toExternalForm();
aoqi@0 389 return new InputSource(Util.escapeSpace(url));
aoqi@0 390 } catch (MalformedURLException e) {
aoqi@0 391 return new InputSource(source.getPath());
aoqi@0 392 }
aoqi@0 393 }
aoqi@0 394
aoqi@0 395 public void addGrammar( File source ) {
aoqi@0 396 addGrammar(fileToInputSource(source));
aoqi@0 397 }
aoqi@0 398
aoqi@0 399 /**
aoqi@0 400 * Recursively scan directories and add all XSD files in it.
aoqi@0 401 */
aoqi@0 402 public void addGrammarRecursive( File dir ) {
aoqi@0 403 addRecursive(dir,".xsd",grammars);
aoqi@0 404 }
aoqi@0 405
aoqi@0 406 private void addRecursive( File dir, String suffix, List<InputSource> result ) {
aoqi@0 407 File[] files = dir.listFiles();
aoqi@0 408 if(files==null) return; // work defensively
aoqi@0 409
aoqi@0 410 for( File f : files ) {
aoqi@0 411 if(f.isDirectory())
aoqi@0 412 addRecursive(f,suffix,result);
aoqi@0 413 else
aoqi@0 414 if(f.getPath().endsWith(suffix))
aoqi@0 415 result.add(absolutize(fileToInputSource(f)));
aoqi@0 416 }
aoqi@0 417 }
aoqi@0 418
aoqi@0 419
aoqi@0 420 private InputSource absolutize(InputSource is) {
aoqi@0 421 // absolutize all the system IDs in the input, so that we can map system IDs to DOM trees.
aoqi@0 422 try {
aoqi@0 423 URL baseURL = new File(".").getCanonicalFile().toURL();
aoqi@0 424 is.setSystemId( new URL(baseURL,is.getSystemId()).toExternalForm() );
aoqi@0 425 } catch( IOException e ) {
aoqi@0 426 logger.log(Level.FINE, "{0}, {1}", new Object[]{is.getSystemId(), e.getLocalizedMessage()});
aoqi@0 427 }
aoqi@0 428 return is;
aoqi@0 429 }
aoqi@0 430
aoqi@0 431 /** Input external binding files. */
aoqi@0 432 public InputSource[] getBindFiles() {
aoqi@0 433 return bindFiles.toArray(new InputSource[bindFiles.size()]);
aoqi@0 434 }
aoqi@0 435
aoqi@0 436 /**
aoqi@0 437 * Adds a new binding file.
aoqi@0 438 */
aoqi@0 439 public void addBindFile( InputSource is ) {
aoqi@0 440 bindFiles.add(absolutize(is));
aoqi@0 441 }
aoqi@0 442
aoqi@0 443 /**
aoqi@0 444 * Adds a new binding file.
aoqi@0 445 */
aoqi@0 446 public void addBindFile( File bindFile ) {
aoqi@0 447 bindFiles.add(fileToInputSource(bindFile));
aoqi@0 448 }
aoqi@0 449
aoqi@0 450 /**
aoqi@0 451 * Recursively scan directories and add all ".xjb" files in it.
aoqi@0 452 */
aoqi@0 453 public void addBindFileRecursive( File dir ) {
aoqi@0 454 addRecursive(dir,".xjb",bindFiles);
aoqi@0 455 }
aoqi@0 456
aoqi@0 457 public final List<URL> classpaths = new ArrayList<URL>();
aoqi@0 458 /**
aoqi@0 459 * Gets a classLoader that can load classes specified via the
aoqi@0 460 * -classpath option.
aoqi@0 461 */
aoqi@0 462 public ClassLoader getUserClassLoader( ClassLoader parent ) {
aoqi@0 463 if (classpaths.isEmpty())
aoqi@0 464 return parent;
aoqi@0 465 return new URLClassLoader(
aoqi@0 466 classpaths.toArray(new URL[classpaths.size()]),parent);
aoqi@0 467 }
aoqi@0 468
aoqi@0 469
aoqi@0 470 /**
aoqi@0 471 * Parses an option <code>args[i]</code> and return
aoqi@0 472 * the number of tokens consumed.
aoqi@0 473 *
aoqi@0 474 * @return
aoqi@0 475 * 0 if the argument is not understood. Returning 0
aoqi@0 476 * will let the caller report an error.
aoqi@0 477 * @exception BadCommandLineException
aoqi@0 478 * If the callee wants to provide a custom message for an error.
aoqi@0 479 */
aoqi@0 480 public int parseArgument( String[] args, int i ) throws BadCommandLineException {
aoqi@0 481 if (args[i].equals("-classpath") || args[i].equals("-cp")) {
aoqi@0 482 String a = requireArgument(args[i], args, ++i);
aoqi@0 483 for (String p : a.split(File.pathSeparator)) {
aoqi@0 484 File file = new File(p);
aoqi@0 485 try {
aoqi@0 486 classpaths.add(file.toURL());
aoqi@0 487 } catch (MalformedURLException e) {
aoqi@0 488 throw new BadCommandLineException(
aoqi@0 489 Messages.format(Messages.NOT_A_VALID_FILENAME,file),e);
aoqi@0 490 }
aoqi@0 491 }
aoqi@0 492 return 2;
aoqi@0 493 }
aoqi@0 494 if (args[i].equals("-d")) {
aoqi@0 495 targetDir = new File(requireArgument("-d",args,++i));
aoqi@0 496 if( !targetDir.exists() )
aoqi@0 497 throw new BadCommandLineException(
aoqi@0 498 Messages.format(Messages.NON_EXISTENT_DIR,targetDir));
aoqi@0 499 return 2;
aoqi@0 500 }
aoqi@0 501 if (args[i].equals("-readOnly")) {
aoqi@0 502 readOnly = true;
aoqi@0 503 return 1;
aoqi@0 504 }
aoqi@0 505 if (args[i].equals("-p")) {
aoqi@0 506 defaultPackage = requireArgument("-p",args,++i);
aoqi@0 507 if(defaultPackage.length()==0) { // user specified default package
aoqi@0 508 // there won't be any package to annotate, so disable them
aoqi@0 509 // automatically as a usability feature
aoqi@0 510 packageLevelAnnotations = false;
aoqi@0 511 }
aoqi@0 512 return 2;
aoqi@0 513 }
aoqi@0 514 if (args[i].equals("-debug")) {
aoqi@0 515 debugMode = true;
aoqi@0 516 verbose = true;
aoqi@0 517 return 1;
aoqi@0 518 }
aoqi@0 519 if (args[i].equals("-nv")) {
aoqi@0 520 strictCheck = false;
aoqi@0 521 return 1;
aoqi@0 522 }
aoqi@0 523 if( args[i].equals("-npa")) {
aoqi@0 524 packageLevelAnnotations = false;
aoqi@0 525 return 1;
aoqi@0 526 }
aoqi@0 527 if( args[i].equals("-no-header")) {
aoqi@0 528 noFileHeader = true;
aoqi@0 529 return 1;
aoqi@0 530 }
aoqi@0 531 if (args[i].equals("-verbose")) {
aoqi@0 532 verbose = true;
aoqi@0 533 return 1;
aoqi@0 534 }
aoqi@0 535 if (args[i].equals("-quiet")) {
aoqi@0 536 quiet = true;
aoqi@0 537 return 1;
aoqi@0 538 }
aoqi@0 539 if (args[i].equals("-XexplicitAnnotation")) {
aoqi@0 540 runtime14 = true;
aoqi@0 541 return 1;
aoqi@0 542 }
aoqi@0 543 if (args[i].equals("-enableIntrospection")) {
aoqi@0 544 enableIntrospection = true;
aoqi@0 545 return 1;
aoqi@0 546 }
aoqi@0 547 if (args[i].equals("-disableXmlSecurity")) {
aoqi@0 548 disableXmlSecurity = true;
aoqi@0 549 return 1;
aoqi@0 550 }
aoqi@0 551 if (args[i].equals("-contentForWildcard")) {
aoqi@0 552 contentForWildcard = true;
aoqi@0 553 return 1;
aoqi@0 554 }
aoqi@0 555 if (args[i].equals("-XautoNameResolution")) {
aoqi@0 556 automaticNameConflictResolution = true;
aoqi@0 557 return 1;
aoqi@0 558 }
aoqi@0 559 if (args[i].equals("-b")) {
aoqi@0 560 addFile(requireArgument("-b",args,++i),bindFiles,".xjb");
aoqi@0 561 return 2;
aoqi@0 562 }
aoqi@0 563 if (args[i].equals("-dtd")) {
aoqi@0 564 schemaLanguage = Language.DTD;
aoqi@0 565 return 1;
aoqi@0 566 }
aoqi@0 567 if (args[i].equals("-relaxng")) {
aoqi@0 568 schemaLanguage = Language.RELAXNG;
aoqi@0 569 return 1;
aoqi@0 570 }
aoqi@0 571 if (args[i].equals("-relaxng-compact")) {
aoqi@0 572 schemaLanguage = Language.RELAXNG_COMPACT;
aoqi@0 573 return 1;
aoqi@0 574 }
aoqi@0 575 if (args[i].equals("-xmlschema")) {
aoqi@0 576 schemaLanguage = Language.XMLSCHEMA;
aoqi@0 577 return 1;
aoqi@0 578 }
aoqi@0 579 if (args[i].equals("-wsdl")) {
aoqi@0 580 schemaLanguage = Language.WSDL;
aoqi@0 581 return 1;
aoqi@0 582 }
aoqi@0 583 if (args[i].equals("-extension")) {
aoqi@0 584 compatibilityMode = EXTENSION;
aoqi@0 585 return 1;
aoqi@0 586 }
aoqi@0 587 if (args[i].equals("-target")) {
aoqi@0 588 String token = requireArgument("-target",args,++i);
aoqi@0 589 target = SpecVersion.parse(token);
aoqi@0 590 if(target==null)
aoqi@0 591 throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_TARGET_VERSION,token));
aoqi@0 592 return 2;
aoqi@0 593 }
aoqi@0 594 if (args[i].equals("-httpproxyfile")) {
aoqi@0 595 if (i == args.length - 1 || args[i + 1].startsWith("-")) {
aoqi@0 596 throw new BadCommandLineException(
aoqi@0 597 Messages.format(Messages.MISSING_PROXYFILE));
aoqi@0 598 }
aoqi@0 599
aoqi@0 600 File file = new File(args[++i]);
aoqi@0 601 if(!file.exists()) {
aoqi@0 602 throw new BadCommandLineException(
aoqi@0 603 Messages.format(Messages.NO_SUCH_FILE,file));
aoqi@0 604 }
aoqi@0 605
aoqi@0 606 try {
aoqi@0 607 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
aoqi@0 608 parseProxy(in.readLine());
aoqi@0 609 in.close();
aoqi@0 610 } catch (IOException e) {
aoqi@0 611 throw new BadCommandLineException(
aoqi@0 612 Messages.format(Messages.FAILED_TO_PARSE,file,e.getMessage()),e);
aoqi@0 613 }
aoqi@0 614
aoqi@0 615 return 2;
aoqi@0 616 }
aoqi@0 617 if (args[i].equals("-httpproxy")) {
aoqi@0 618 if (i == args.length - 1 || args[i + 1].startsWith("-")) {
aoqi@0 619 throw new BadCommandLineException(
aoqi@0 620 Messages.format(Messages.MISSING_PROXY));
aoqi@0 621 }
aoqi@0 622
aoqi@0 623 parseProxy(args[++i]);
aoqi@0 624 return 2;
aoqi@0 625 }
aoqi@0 626 if (args[i].equals("-host")) {
aoqi@0 627 proxyHost = requireArgument("-host",args,++i);
aoqi@0 628 return 2;
aoqi@0 629 }
aoqi@0 630 if (args[i].equals("-port")) {
aoqi@0 631 proxyPort = requireArgument("-port",args,++i);
aoqi@0 632 return 2;
aoqi@0 633 }
aoqi@0 634 if( args[i].equals("-catalog") ) {
aoqi@0 635 // use Sun's "XML Entity and URI Resolvers" by Norman Walsh
aoqi@0 636 // to resolve external entities.
aoqi@0 637 // http://www.sun.com/xml/developers/resolver/
aoqi@0 638
aoqi@0 639 File catalogFile = new File(requireArgument("-catalog",args,++i));
aoqi@0 640 try {
aoqi@0 641 addCatalog(catalogFile);
aoqi@0 642 } catch (IOException e) {
aoqi@0 643 throw new BadCommandLineException(
aoqi@0 644 Messages.format(Messages.FAILED_TO_PARSE,catalogFile,e.getMessage()),e);
aoqi@0 645 }
aoqi@0 646 return 2;
aoqi@0 647 }
aoqi@0 648 if( args[i].equals("-Xtest-class-name-allocator") ) {
aoqi@0 649 classNameAllocator = new ClassNameAllocator() {
aoqi@0 650 public String assignClassName(String packageName, String className) {
aoqi@0 651 System.out.printf("assignClassName(%s,%s)\n",packageName,className);
aoqi@0 652 return className+"_Type";
aoqi@0 653 }
aoqi@0 654 };
aoqi@0 655 return 1;
aoqi@0 656 }
aoqi@0 657
aoqi@0 658 if (args[i].equals("-encoding")) {
aoqi@0 659 encoding = requireArgument("-encoding", args, ++i);
aoqi@0 660 try {
aoqi@0 661 if (!Charset.isSupported(encoding)) {
aoqi@0 662 throw new BadCommandLineException(
aoqi@0 663 Messages.format(Messages.UNSUPPORTED_ENCODING, encoding));
aoqi@0 664 }
aoqi@0 665 } catch (IllegalCharsetNameException icne) {
aoqi@0 666 throw new BadCommandLineException(
aoqi@0 667 Messages.format(Messages.UNSUPPORTED_ENCODING, encoding));
aoqi@0 668 }
aoqi@0 669 return 2;
aoqi@0 670 }
aoqi@0 671
aoqi@0 672 // see if this is one of the extensions
aoqi@0 673 for( Plugin plugin : getAllPlugins() ) {
aoqi@0 674 try {
aoqi@0 675 if( ('-'+plugin.getOptionName()).equals(args[i]) ) {
aoqi@0 676 activePlugins.add(plugin);
aoqi@0 677 plugin.onActivated(this);
aoqi@0 678 pluginURIs.addAll(plugin.getCustomizationURIs());
aoqi@0 679
aoqi@0 680 // give the plugin a chance to parse arguments to this option.
aoqi@0 681 // this is new in 2.1, and due to the backward compatibility reason,
aoqi@0 682 // if plugin didn't understand it, we still return 1 to indicate
aoqi@0 683 // that this option is consumed.
aoqi@0 684 int r = plugin.parseArgument(this,args,i);
aoqi@0 685 if(r!=0)
aoqi@0 686 return r;
aoqi@0 687 else
aoqi@0 688 return 1;
aoqi@0 689 }
aoqi@0 690
aoqi@0 691 int r = plugin.parseArgument(this,args,i);
aoqi@0 692 if(r!=0) return r;
aoqi@0 693 } catch (IOException e) {
aoqi@0 694 throw new BadCommandLineException(e.getMessage(),e);
aoqi@0 695 }
aoqi@0 696 }
aoqi@0 697
aoqi@0 698 return 0; // unrecognized
aoqi@0 699 }
aoqi@0 700
aoqi@0 701 private void parseProxy(String text) throws BadCommandLineException {
aoqi@0 702 int i = text.lastIndexOf('@');
aoqi@0 703 int j = text.lastIndexOf(':');
aoqi@0 704
aoqi@0 705 if (i > 0) {
aoqi@0 706 proxyAuth = text.substring(0, i);
aoqi@0 707 if (j > i) {
aoqi@0 708 proxyHost = text.substring(i + 1, j);
aoqi@0 709 proxyPort = text.substring(j + 1);
aoqi@0 710 } else {
aoqi@0 711 proxyHost = text.substring(i + 1);
aoqi@0 712 proxyPort = "80";
aoqi@0 713 }
aoqi@0 714 } else {
aoqi@0 715 //no auth info
aoqi@0 716 if (j < 0) {
aoqi@0 717 //no port
aoqi@0 718 proxyHost = text;
aoqi@0 719 proxyPort = "80";
aoqi@0 720 } else {
aoqi@0 721 proxyHost = text.substring(0, j);
aoqi@0 722 proxyPort = text.substring(j + 1);
aoqi@0 723 }
aoqi@0 724 }
aoqi@0 725 try {
aoqi@0 726 Integer.valueOf(proxyPort);
aoqi@0 727 } catch (NumberFormatException e) {
aoqi@0 728 throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_PROXY,text));
aoqi@0 729 }
aoqi@0 730 }
aoqi@0 731
aoqi@0 732 /**
aoqi@0 733 * Obtains an operand and reports an error if it's not there.
aoqi@0 734 */
aoqi@0 735 public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException {
aoqi@0 736 if (i == args.length || args[i].startsWith("-")) {
aoqi@0 737 throw new BadCommandLineException(
aoqi@0 738 Messages.format(Messages.MISSING_OPERAND,optionName));
aoqi@0 739 }
aoqi@0 740 return args[i];
aoqi@0 741 }
aoqi@0 742
aoqi@0 743 /**
aoqi@0 744 * Parses a token to a file (or a set of files)
aoqi@0 745 * and add them as {@link InputSource} to the specified list.
aoqi@0 746 *
aoqi@0 747 * @param suffix
aoqi@0 748 * If the given token is a directory name, we do a recusive search
aoqi@0 749 * and find all files that have the given suffix.
aoqi@0 750 */
aoqi@0 751 private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException {
aoqi@0 752 Object src;
aoqi@0 753 try {
aoqi@0 754 src = Util.getFileOrURL(name);
aoqi@0 755 } catch (IOException e) {
aoqi@0 756 throw new BadCommandLineException(
aoqi@0 757 Messages.format(Messages.NOT_A_FILE_NOR_URL,name));
aoqi@0 758 }
aoqi@0 759 if(src instanceof URL) {
aoqi@0 760 target.add(absolutize(new InputSource(Util.escapeSpace(((URL)src).toExternalForm()))));
aoqi@0 761 } else {
aoqi@0 762 File fsrc = (File)src;
aoqi@0 763 if(fsrc.isDirectory()) {
aoqi@0 764 addRecursive(fsrc,suffix,target);
aoqi@0 765 } else {
aoqi@0 766 target.add(absolutize(fileToInputSource(fsrc)));
aoqi@0 767 }
aoqi@0 768 }
aoqi@0 769 }
aoqi@0 770
aoqi@0 771 /**
aoqi@0 772 * Adds a new catalog file.
aoqi@0 773 */
aoqi@0 774 public void addCatalog(File catalogFile) throws IOException {
aoqi@0 775 if(entityResolver==null) {
aoqi@0 776 CatalogManager.getStaticManager().setIgnoreMissingProperties(true);
aoqi@0 777 entityResolver = new CatalogResolver(true);
aoqi@0 778 }
aoqi@0 779 ((CatalogResolver)entityResolver).getCatalog().parseCatalog(catalogFile.getPath());
aoqi@0 780 }
aoqi@0 781
aoqi@0 782 /**
aoqi@0 783 * Parses arguments and fill fields of this object.
aoqi@0 784 *
aoqi@0 785 * @exception BadCommandLineException
aoqi@0 786 * thrown when there's a problem in the command-line arguments
aoqi@0 787 */
aoqi@0 788 public void parseArguments( String[] args ) throws BadCommandLineException {
aoqi@0 789
aoqi@0 790 for (int i = 0; i < args.length; i++) {
aoqi@0 791 if(args[i].length()==0)
aoqi@0 792 throw new BadCommandLineException();
aoqi@0 793 if (args[i].charAt(0) == '-') {
aoqi@0 794 int j = parseArgument(args,i);
aoqi@0 795 if(j==0)
aoqi@0 796 throw new BadCommandLineException(
aoqi@0 797 Messages.format(Messages.UNRECOGNIZED_PARAMETER, args[i]));
aoqi@0 798 i += (j-1);
aoqi@0 799 } else {
aoqi@0 800 if(args[i].endsWith(".jar"))
aoqi@0 801 scanEpisodeFile(new File(args[i]));
aoqi@0 802 else
aoqi@0 803 addFile(args[i],grammars,".xsd");
aoqi@0 804 }
aoqi@0 805 }
aoqi@0 806
aoqi@0 807 // configure proxy
aoqi@0 808 if (proxyHost != null || proxyPort != null) {
aoqi@0 809 if (proxyHost != null && proxyPort != null) {
aoqi@0 810 System.setProperty("http.proxyHost", proxyHost);
aoqi@0 811 System.setProperty("http.proxyPort", proxyPort);
aoqi@0 812 System.setProperty("https.proxyHost", proxyHost);
aoqi@0 813 System.setProperty("https.proxyPort", proxyPort);
aoqi@0 814 } else if (proxyHost == null) {
aoqi@0 815 throw new BadCommandLineException(
aoqi@0 816 Messages.format(Messages.MISSING_PROXYHOST));
aoqi@0 817 } else {
aoqi@0 818 throw new BadCommandLineException(
aoqi@0 819 Messages.format(Messages.MISSING_PROXYPORT));
aoqi@0 820 }
aoqi@0 821 if (proxyAuth != null) {
aoqi@0 822 DefaultAuthenticator.getAuthenticator().setProxyAuth(proxyAuth);
aoqi@0 823 }
aoqi@0 824 }
aoqi@0 825
aoqi@0 826 if (grammars.isEmpty())
aoqi@0 827 throw new BadCommandLineException(
aoqi@0 828 Messages.format(Messages.MISSING_GRAMMAR));
aoqi@0 829
aoqi@0 830 if( schemaLanguage==null )
aoqi@0 831 schemaLanguage = guessSchemaLanguage();
aoqi@0 832
aoqi@0 833 // if(target==SpecVersion.V2_2 && !isExtensionMode())
aoqi@0 834 // throw new BadCommandLineException(
aoqi@0 835 // "Currently 2.2 is still not finalized yet, so using it requires the -extension switch." +
aoqi@0 836 // "NOTE THAT 2.2 SPEC MAY CHANGE BEFORE IT BECOMES FINAL.");
aoqi@0 837
aoqi@0 838 if(pluginLoadFailure!=null)
aoqi@0 839 throw new BadCommandLineException(
aoqi@0 840 Messages.format(Messages.PLUGIN_LOAD_FAILURE,pluginLoadFailure));
aoqi@0 841 }
aoqi@0 842
aoqi@0 843 /**
aoqi@0 844 * Finds the <tt>META-INF/sun-jaxb.episode</tt> file to add as a binding customization.
aoqi@0 845 */
aoqi@0 846 public void scanEpisodeFile(File jar) throws BadCommandLineException {
aoqi@0 847 try {
aoqi@0 848 URLClassLoader ucl = new URLClassLoader(new URL[]{jar.toURL()});
aoqi@0 849 Enumeration<URL> resources = ucl.findResources("META-INF/sun-jaxb.episode");
aoqi@0 850 while (resources.hasMoreElements()) {
aoqi@0 851 URL url = resources.nextElement();
aoqi@0 852 addBindFile(new InputSource(url.toExternalForm()));
aoqi@0 853 }
aoqi@0 854 } catch (IOException e) {
aoqi@0 855 throw new BadCommandLineException(
aoqi@0 856 Messages.format(Messages.FAILED_TO_LOAD,jar,e.getMessage()), e);
aoqi@0 857 }
aoqi@0 858 }
aoqi@0 859
aoqi@0 860
aoqi@0 861 /**
aoqi@0 862 * Guesses the schema language.
aoqi@0 863 */
aoqi@0 864 public Language guessSchemaLanguage() {
aoqi@0 865
aoqi@0 866 // otherwise, use the file extension.
aoqi@0 867 // not a good solution, but very easy.
aoqi@0 868 if ((grammars != null) && (grammars.size() > 0)) {
aoqi@0 869 String name = grammars.get(0).getSystemId().toLowerCase();
aoqi@0 870
aoqi@0 871 if (name.endsWith(".rng"))
aoqi@0 872 return Language.RELAXNG;
aoqi@0 873 if (name.endsWith(".rnc"))
aoqi@0 874 return Language.RELAXNG_COMPACT;
aoqi@0 875 if (name.endsWith(".dtd"))
aoqi@0 876 return Language.DTD;
aoqi@0 877 if (name.endsWith(".wsdl"))
aoqi@0 878 return Language.WSDL;
aoqi@0 879 }
aoqi@0 880
aoqi@0 881 // by default, assume XML Schema
aoqi@0 882 return Language.XMLSCHEMA;
aoqi@0 883 }
aoqi@0 884
aoqi@0 885 /**
aoqi@0 886 * Creates a configured CodeWriter that produces files into the specified directory.
aoqi@0 887 */
aoqi@0 888 public CodeWriter createCodeWriter() throws IOException {
aoqi@0 889 return createCodeWriter(new FileCodeWriter( targetDir, readOnly, encoding ));
aoqi@0 890 }
aoqi@0 891
aoqi@0 892 /**
aoqi@0 893 * Creates a configured CodeWriter that produces files into the specified directory.
aoqi@0 894 */
aoqi@0 895 public CodeWriter createCodeWriter( CodeWriter core ) {
aoqi@0 896 if(noFileHeader)
aoqi@0 897 return core;
aoqi@0 898
aoqi@0 899 return new PrologCodeWriter( core,getPrologComment() );
aoqi@0 900 }
aoqi@0 901
aoqi@0 902 /**
aoqi@0 903 * Gets the string suitable to be used as the prolog comment baked into artifacts.
aoqi@0 904 * This is the string like "This file was generated by the JAXB RI on YYYY/mm/dd..."
aoqi@0 905 */
aoqi@0 906 public String getPrologComment() {
aoqi@0 907 // generate format syntax: <date> 'at' <time>
aoqi@0 908 String format =
aoqi@0 909 Messages.format(Messages.DATE_FORMAT)
aoqi@0 910 + " '"
aoqi@0 911 + Messages.format(Messages.AT)
aoqi@0 912 + "' "
aoqi@0 913 + Messages.format(Messages.TIME_FORMAT);
aoqi@0 914 SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.ENGLISH);
aoqi@0 915
aoqi@0 916 return Messages.format(
aoqi@0 917 Messages.FILE_PROLOG_COMMENT,
aoqi@0 918 dateFormat.format(new Date()));
aoqi@0 919 }
aoqi@0 920
aoqi@0 921 /**
aoqi@0 922 * If a plugin failed to load, report.
aoqi@0 923 */
aoqi@0 924 private static String pluginLoadFailure;
aoqi@0 925
aoqi@0 926 /**
aoqi@0 927 * Looks for all "META-INF/services/[className]" files and
aoqi@0 928 * create one instance for each class name found inside this file.
aoqi@0 929 */
aoqi@0 930 private static <T> T[] findServices( Class<T> clazz, ClassLoader classLoader ) {
aoqi@0 931 // if true, print debug output
aoqi@0 932 final boolean debug = com.sun.tools.internal.xjc.util.Util.getSystemProperty(Options.class,"findServices")!=null;
aoqi@0 933
aoqi@0 934 // if we are running on Mustang or Dolphin, use ServiceLoader
aoqi@0 935 // so that we can take advantage of JSR-277 module system.
aoqi@0 936 try {
aoqi@0 937 Class<?> serviceLoader = Class.forName("java.util.ServiceLoader");
aoqi@0 938 if(debug)
aoqi@0 939 System.out.println("Using java.util.ServiceLoader");
aoqi@0 940 Iterable<T> itr = (Iterable<T>)serviceLoader.getMethod("load",Class.class,ClassLoader.class).invoke(null,clazz,classLoader);
aoqi@0 941 List<T> r = new ArrayList<T>();
aoqi@0 942 for (T t : itr)
aoqi@0 943 r.add(t);
aoqi@0 944 return r.toArray((T[])Array.newInstance(clazz,r.size()));
aoqi@0 945 } catch (ClassNotFoundException e) {
aoqi@0 946 // fall through
aoqi@0 947 } catch (IllegalAccessException e) {
aoqi@0 948 Error x = new IllegalAccessError();
aoqi@0 949 x.initCause(e);
aoqi@0 950 throw x;
aoqi@0 951 } catch (InvocationTargetException e) {
aoqi@0 952 Throwable x = e.getTargetException();
aoqi@0 953 if (x instanceof RuntimeException)
aoqi@0 954 throw (RuntimeException) x;
aoqi@0 955 if (x instanceof Error)
aoqi@0 956 throw (Error) x;
aoqi@0 957 throw new Error(x);
aoqi@0 958 } catch (NoSuchMethodException e) {
aoqi@0 959 Error x = new NoSuchMethodError();
aoqi@0 960 x.initCause(e);
aoqi@0 961 throw x;
aoqi@0 962 }
aoqi@0 963
aoqi@0 964 String serviceId = "META-INF/services/" + clazz.getName();
aoqi@0 965
aoqi@0 966 // used to avoid creating the same instance twice
aoqi@0 967 Set<String> classNames = new HashSet<String>();
aoqi@0 968
aoqi@0 969 if(debug) {
aoqi@0 970 System.out.println("Looking for "+serviceId+" for add-ons");
aoqi@0 971 }
aoqi@0 972
aoqi@0 973 // try to find services in CLASSPATH
aoqi@0 974 try {
aoqi@0 975 Enumeration<URL> e = classLoader.getResources(serviceId);
aoqi@0 976 if(e==null) return (T[])Array.newInstance(clazz,0);
aoqi@0 977
aoqi@0 978 ArrayList<T> a = new ArrayList<T>();
aoqi@0 979 while(e.hasMoreElements()) {
aoqi@0 980 URL url = e.nextElement();
aoqi@0 981 BufferedReader reader=null;
aoqi@0 982
aoqi@0 983 if(debug) {
aoqi@0 984 System.out.println("Checking "+url+" for an add-on");
aoqi@0 985 }
aoqi@0 986
aoqi@0 987 try {
aoqi@0 988 reader = new BufferedReader(new InputStreamReader(url.openStream()));
aoqi@0 989 String impl;
aoqi@0 990 while((impl = reader.readLine())!=null ) {
aoqi@0 991 // try to instanciate the object
aoqi@0 992 impl = impl.trim();
aoqi@0 993 if(classNames.add(impl)) {
aoqi@0 994 Class implClass = classLoader.loadClass(impl);
aoqi@0 995 if(!clazz.isAssignableFrom(implClass)) {
aoqi@0 996 pluginLoadFailure = impl+" is not a subclass of "+clazz+". Skipping";
aoqi@0 997 if(debug)
aoqi@0 998 System.out.println(pluginLoadFailure);
aoqi@0 999 continue;
aoqi@0 1000 }
aoqi@0 1001 if(debug) {
aoqi@0 1002 System.out.println("Attempting to instanciate "+impl);
aoqi@0 1003 }
aoqi@0 1004 a.add(clazz.cast(implClass.newInstance()));
aoqi@0 1005 }
aoqi@0 1006 }
aoqi@0 1007 reader.close();
aoqi@0 1008 } catch( Exception ex ) {
aoqi@0 1009 // let it go.
aoqi@0 1010 StringWriter w = new StringWriter();
aoqi@0 1011 ex.printStackTrace(new PrintWriter(w));
aoqi@0 1012 pluginLoadFailure = w.toString();
aoqi@0 1013 if(debug) {
aoqi@0 1014 System.out.println(pluginLoadFailure);
aoqi@0 1015 }
aoqi@0 1016 if( reader!=null ) {
aoqi@0 1017 try {
aoqi@0 1018 reader.close();
aoqi@0 1019 } catch( IOException ex2 ) {
aoqi@0 1020 // ignore
aoqi@0 1021 }
aoqi@0 1022 }
aoqi@0 1023 }
aoqi@0 1024 }
aoqi@0 1025
aoqi@0 1026 return a.toArray((T[])Array.newInstance(clazz,a.size()));
aoqi@0 1027 } catch( Throwable e ) {
aoqi@0 1028 // ignore any error
aoqi@0 1029 StringWriter w = new StringWriter();
aoqi@0 1030 e.printStackTrace(new PrintWriter(w));
aoqi@0 1031 pluginLoadFailure = w.toString();
aoqi@0 1032 if(debug) {
aoqi@0 1033 System.out.println(pluginLoadFailure);
aoqi@0 1034 }
aoqi@0 1035 return (T[])Array.newInstance(clazz,0);
aoqi@0 1036 }
aoqi@0 1037 }
aoqi@0 1038
aoqi@0 1039 // this is a convenient place to expose the build version to xjc plugins
aoqi@0 1040 public static String getBuildID() {
aoqi@0 1041 return Messages.format(Messages.BUILD_ID);
aoqi@0 1042 }
aoqi@0 1043
aoqi@0 1044 public static String normalizeSystemId(String systemId) {
aoqi@0 1045 try {
aoqi@0 1046 systemId = new URI(systemId).normalize().toString();
aoqi@0 1047 } catch (URISyntaxException e) {
aoqi@0 1048 // leave the system ID untouched. In my experience URI is often too strict
aoqi@0 1049 }
aoqi@0 1050 return systemId;
aoqi@0 1051 }
aoqi@0 1052
aoqi@0 1053 }

mercurial