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