1 /*
   2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.internal.ws.wscompile;
  27 
  28 import com.sun.codemodel.internal.JCodeModel;
  29 import com.sun.tools.internal.ws.processor.generator.GeneratorExtension;
  30 import com.sun.tools.internal.ws.resources.ConfigurationMessages;
  31 import com.sun.tools.internal.ws.resources.WscompileMessages;
  32 import com.sun.tools.internal.ws.util.ForkEntityResolver;
  33 import com.sun.tools.internal.ws.wsdl.document.jaxws.JAXWSBindingsConstants;
  34 import com.sun.tools.internal.ws.wsdl.document.schema.SchemaConstants;
  35 import com.sun.tools.internal.xjc.api.SchemaCompiler;
  36 import com.sun.tools.internal.xjc.api.SpecVersion;
  37 import com.sun.tools.internal.xjc.api.XJC;
  38 import com.sun.tools.internal.xjc.reader.Util;
  39 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
  40 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
  41 import com.sun.xml.internal.ws.util.ServiceFinder;
  42 import com.sun.xml.internal.ws.util.JAXWSUtils;
  43 import com.sun.xml.internal.ws.util.xml.XmlUtil;
  44 import org.w3c.dom.Element;
  45 import org.xml.sax.EntityResolver;
  46 import org.xml.sax.InputSource;
  47 import org.xml.sax.helpers.LocatorImpl;
  48 
  49 import javax.xml.namespace.QName;
  50 import javax.xml.stream.XMLStreamReader;
  51 
  52 import java.io.ByteArrayInputStream;
  53 import java.io.ByteArrayOutputStream;
  54 import java.io.File;
  55 import java.io.IOException;
  56 import java.io.InputStream;
  57 import java.io.Reader;
  58 import java.lang.reflect.Array;
  59 import java.net.MalformedURLException;
  60 import java.net.URL;
  61 import java.util.ArrayList;
  62 import java.util.Arrays;
  63 import java.util.List;
  64 import java.util.HashMap;
  65 import java.util.logging.Level;
  66 import java.util.logging.Logger;
  67 
  68 /**
  69  * @author Vivek Pandey
  70  */
  71 public class WsimportOptions extends Options {
  72     /**
  73      * -wsdlLocation
  74      */
  75     public String wsdlLocation;
  76 
  77     /**
  78      * Actually stores {@link com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver}, but the field
  79      * type is made to {@link org.xml.sax.EntityResolver} so that XJC can be
  80      * used even if resolver.jar is not available in the classpath.
  81      */
  82     public EntityResolver entityResolver = null;
  83 
  84     /**
  85      * The -p option that should control the default Java package that
  86      * will contain the generated code. Null if unspecified.
  87      */
  88     public String defaultPackage = null;
  89 
  90     /**
  91      * The -clientjar option to package client artifacts as jar
  92      */
  93     public String clientjar = null;
  94 
  95     /**
  96      * -XadditionalHeaders
  97      */
  98     public boolean additionalHeaders;
  99 
 100     /**
 101      * The option indicates the dir where the jwsImpl will be generated.
 102      */
 103     public File implDestDir = null;
 104 
 105     /**
 106      * optional, generated impl file only for the ordered serviceName
 107      * Note: It is a QName string, formatted as: "{" + Namespace URI + "}" + local part
 108      */
 109     public String implServiceName = null;
 110 
 111     /**
 112      * optional, generated impl file only for the ordered portName
 113      * Note: It is a QName string, formatted as: "{" + Namespace URI + "}" + local part
 114      */
 115     public String implPortName = null;
 116 
 117     /**
 118      * optional, if true JWS file is generated
 119      */
 120     public boolean isGenerateJWS = false;
 121 
 122     /**
 123      * Setting disableSSLHostVerification to true disables the SSL Hostname verification while fetching the wsdls.
 124      * -XdisableSSLHostVerification
 125      */
 126     public boolean disableSSLHostnameVerification;
 127 
 128     /**
 129      * Setting useBaseResourceAndURLToLoadWSDL to true causes generated Service classes to load the WSDL file from
 130      * a URL generated from the base resource.
 131      * -XuseBaseResourceAndURLToLoadWSDL
 132      */
 133     public boolean useBaseResourceAndURLToLoadWSDL = false;
 134 
 135     /**
 136      * Java module name in {@code module-info.java}.
 137      */
 138     private String javaModule = null;
 139 
 140     /**
 141      * JAXB's {@link SchemaCompiler} to be used for handling the schema portion.
 142      * This object is also configured through options.
 143      */
 144     private SchemaCompiler schemaCompiler = XJC.createSchemaCompiler();
 145 
 146     /**
 147      * Authentication file
 148      */
 149     public File authFile = null;
 150 
 151     //can user.home value be null?
 152     public static final String defaultAuthfile
 153             = System.getProperty("user.home") + System.getProperty("file.separator")
 154             + ".metro" + System.getProperty("file.separator") + "auth";
 155 
 156     /**
 157      * Setting disableAuthenticator to true disables the DefaultAuthenticator.
 158      * -XdisableAuthenticator
 159      */
 160     public boolean disableAuthenticator;
 161 
 162     public String proxyAuth = null;
 163     private String proxyHost = null;
 164     private String proxyPort = null;
 165 
 166     /**
 167      * Additional arguments
 168      */
 169     public HashMap<String, String> extensionOptions = new HashMap<String, String>();
 170 
 171     /**
 172      * All discovered {@link Plugin}s.
 173      * This is lazily parsed, so that we can take '-cp' option into account.
 174      *
 175      * @see #getAllPlugins()
 176      */
 177     private List<Plugin> allPlugins;
 178 
 179     /**
 180      * {@link Plugin}s that are enabled in this compilation.
 181      */
 182     public final List<Plugin> activePlugins = new ArrayList<Plugin>();
 183 
 184     public JCodeModel getCodeModel() {
 185         if(codeModel == null)
 186             codeModel = new JCodeModel();
 187         return codeModel;
 188     }
 189 
 190     public SchemaCompiler getSchemaCompiler() {
 191         schemaCompiler.setTargetVersion(SpecVersion.parse(target.getVersion()));
 192         if(entityResolver != null) {
 193             //set if its not null so as not to override catalog option specified via xjc args
 194             schemaCompiler.setEntityResolver(entityResolver);
 195         }
 196         return schemaCompiler;
 197     }
 198 
 199     public void setCodeModel(JCodeModel codeModel) {
 200         this.codeModel = codeModel;
 201     }
 202 
 203     private JCodeModel codeModel;
 204 
 205     /**
 206      * This captures jars passed on the commandline and passes them to XJC and puts them in the classpath for compilation
 207      */
 208     public List<String> cmdlineJars = new ArrayList<String>();
 209 
 210     /**
 211      * Gets all the {@link Plugin}s discovered so far.
 212      *
 213      * <p>
 214      * A plugins are enumerated when this method is called for the first time,
 215      * by taking {@link #classpath} into account. That means
 216      * "-cp plugin.jar" has to come before you specify options to enable it.
 217      */
 218     public List<Plugin> getAllPlugins() {
 219         if(allPlugins==null) {
 220             allPlugins = new ArrayList<Plugin>();
 221             allPlugins.addAll(Arrays.asList(findServices(Plugin.class, getClassLoader())));
 222         }
 223         return allPlugins;
 224     }
 225 
 226     /**
 227      * Gets Java module name option.
 228      * @return Java module name option or {@code null} if this option was not set.
 229      */
 230     public String getModuleName() {
 231         return javaModule;
 232     }
 233 
 234      /**
 235      * Parses arguments and fill fields of this object.
 236      *
 237      * @exception BadCommandLineException
 238      *      thrown when there's a problem in the command-line arguments
 239      */
 240     @Override
 241     public final void parseArguments( String[] args ) throws BadCommandLineException {
 242 
 243         for (int i = 0; i < args.length; i++) {
 244             if(args[i].length()==0)
 245                 throw new BadCommandLineException();
 246             if (args[i].charAt(0) == '-') {
 247                 int j = parseArguments(args,i);
 248                 if(j==0)
 249                     throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i]));
 250                 i += (j-1);
 251             } else {
 252                 if(args[i].endsWith(".jar")) {
 253 
 254                     try {
 255                 cmdlineJars.add(args[i]);
 256                 schemaCompiler.getOptions().scanEpisodeFile(new File(args[i]));
 257 
 258             } catch (com.sun.tools.internal.xjc.BadCommandLineException e) {
 259                 //Driver.usage(jaxbOptions,false);
 260                 throw new BadCommandLineException(e.getMessage(), e);
 261             }
 262                 } else{
 263                     addFile(args[i]);
 264                 }
 265             }
 266         }
 267 
 268         if (encoding != null && schemaCompiler.getOptions().encoding == null) {
 269             try {
 270                 schemaCompiler.getOptions().parseArgument(
 271                         new String[] {"-encoding", encoding}, 0);
 272             } catch (com.sun.tools.internal.xjc.BadCommandLineException ex) {
 273                 Logger.getLogger(WsimportOptions.class.getName()).log(Level.SEVERE, null, ex);
 274             }
 275         }
 276 
 277         if(destDir == null)
 278             destDir = new File(".");
 279         if(sourceDir == null)
 280             sourceDir = destDir;
 281     }
 282 
 283     /** -Xno-addressing-databinding option to disable addressing namespace data binding. This is
 284      * experimental switch and will be working as a temporary workaround till
 285      * jaxb can provide a better way to selelctively disable compiling of an
 286      * schema component.
 287      * **/
 288     public boolean noAddressingBbinding;
 289 
 290     @Override
 291     public int parseArguments(String[] args, int i) throws BadCommandLineException {
 292         int j = super.parseArguments(args ,i);
 293         if(j>0) return j;   // understood by the super class
 294 
 295         if (args[i].equals("-b")) {
 296             addBindings(requireArgument("-b", args, ++i));
 297             return 2;
 298         } else if (args[i].equals("-wsdllocation")) {
 299             wsdlLocation = requireArgument("-wsdllocation", args, ++i);
 300             return 2;
 301         } else if (args[i].equals("-XadditionalHeaders")) {
 302             additionalHeaders = true;
 303             return 1;
 304         } else if (args[i].equals("-XdisableSSLHostnameVerification")) {
 305             disableSSLHostnameVerification = true;
 306             return 1;
 307         } else if (args[i].equals("-p")) {
 308             defaultPackage = requireArgument("-p", args, ++i);
 309             return 2;
 310         } else if (args[i].equals("-m")) {
 311             javaModule = requireArgument("-m", args, ++i);
 312             return 2;
 313         } else if (args[i].equals("-catalog")) {
 314             String catalog = requireArgument("-catalog", args, ++i);
 315             try {
 316                 if (entityResolver == null) {
 317                     if (catalog != null && catalog.length() > 0)
 318                         entityResolver = XmlUtil.createEntityResolver(JAXWSUtils.getFileOrURL(JAXWSUtils.absolutize(Util.escapeSpace(catalog))));
 319                 } else if (catalog != null && catalog.length() > 0) {
 320                     EntityResolver er = XmlUtil.createEntityResolver(JAXWSUtils.getFileOrURL(JAXWSUtils.absolutize(Util.escapeSpace(catalog))));
 321                     entityResolver = new ForkEntityResolver(er, entityResolver);
 322                 }
 323             } catch (IOException e) {
 324                 throw new BadCommandLineException(WscompileMessages.WSIMPORT_FAILED_TO_PARSE(catalog, e.getMessage()));
 325             }
 326             return 2;
 327         } else if (args[i].startsWith("-httpproxy:")) {
 328             String value = args[i].substring(11);
 329             if (value.length() == 0) {
 330                 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i]));
 331             }
 332             parseProxy(value);
 333             if (proxyHost != null || proxyPort != null) {
 334                 System.setProperty("proxySet", "true");
 335             }
 336             if (proxyHost != null) {
 337                 System.setProperty("proxyHost", proxyHost);
 338             }
 339             if (proxyPort != null) {
 340                 System.setProperty("proxyPort", proxyPort);
 341             }
 342             return 1;
 343         } else if (args[i].equals("-Xno-addressing-databinding")) {
 344             noAddressingBbinding = true;
 345             return 1;
 346         } else if (args[i].startsWith("-B")) {
 347             // JAXB option pass through.
 348             String[] subCmd = new String[args.length-i];
 349             System.arraycopy(args,i,subCmd,0,subCmd.length);
 350             subCmd[0] = subCmd[0].substring(2); // trim off the first "-B"
 351 
 352             com.sun.tools.internal.xjc.Options jaxbOptions = schemaCompiler.getOptions();
 353             try {
 354                 int r = jaxbOptions.parseArgument(subCmd, 0);
 355                 if(r==0) {
 356                     //Driver.usage(jaxbOptions,false);
 357                     throw new BadCommandLineException(WscompileMessages.WSIMPORT_NO_SUCH_JAXB_OPTION(subCmd[0]));
 358                 }
 359                 return r;
 360             } catch (com.sun.tools.internal.xjc.BadCommandLineException e) {
 361                 //Driver.usage(jaxbOptions,false);
 362                 throw new BadCommandLineException(e.getMessage(),e);
 363             }
 364         } else if (args[i].equals("-Xauthfile")) {
 365             String authfile = requireArgument("-Xauthfile", args, ++i);
 366             authFile = new File(authfile);
 367             return 2;
 368         } else if (args[i].equals("-clientjar")) {
 369             clientjar = requireArgument("-clientjar", args, ++i);
 370             return 2;
 371         } else if (args[i].equals("-implDestDir")) {
 372                         implDestDir = new File(requireArgument("-implDestDir", args, ++i));
 373             if (!implDestDir.exists())
 374               throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(implDestDir.getPath()));
 375                         return 2;
 376         } else if (args[i].equals("-implServiceName")) {
 377                 implServiceName = requireArgument("-implServiceName", args, ++i);
 378           return 2;
 379         } else if (args[i].equals("-implPortName")) {
 380                 implPortName = requireArgument("-implPortName", args, ++i);
 381           return 2;
 382         } else if (args[i].equals("-generateJWS")) {
 383             isGenerateJWS = true;
 384             return 1;
 385         } else if (args[i].equals("-XuseBaseResourceAndURLToLoadWSDL")) {
 386                 useBaseResourceAndURLToLoadWSDL = true;
 387             return 1;
 388         } else if (args[i].equals("-XdisableAuthenticator")) {
 389             disableAuthenticator = true;
 390             return 1;
 391         }
 392 
 393         // handle additional options
 394         for (GeneratorExtension f:ServiceFinder.find(GeneratorExtension.class)) {
 395             if (f.validateOption(args[i])) {
 396                 extensionOptions.put(args[i], requireArgument(args[i], args, ++i));
 397                 return 2;
 398             }
 399         }
 400 
 401         // see if this is one of the extensions
 402         for( Plugin plugin : getAllPlugins() ) {
 403             try {
 404                 if(('-' + plugin.getOptionName()).equals(args[i])) {
 405                     activePlugins.add(plugin);
 406                     plugin.onActivated(this);
 407                     return 1;
 408                 }
 409                 int r = plugin.parseArgument(this, args, i);
 410                 if (r != 0) {
 411                     return r;
 412                 }
 413             } catch (IOException e) {
 414                 throw new BadCommandLineException(e.getMessage(),e);
 415             }
 416         }
 417 
 418         return 0; // what's this option?
 419     }
 420 
 421     public void validate() throws BadCommandLineException {
 422         if (wsdls.isEmpty()) {
 423             throw new BadCommandLineException(WscompileMessages.WSIMPORT_MISSING_FILE());
 424         }
 425 
 426         if(wsdlLocation !=null && clientjar != null) {
 427            throw new BadCommandLineException(WscompileMessages.WSIMPORT_WSDLLOCATION_CLIENTJAR());
 428         }
 429         if(wsdlLocation == null){
 430             wsdlLocation = wsdls.get(0).getSystemId();
 431         }
 432 
 433 
 434     }
 435 
 436     @Override
 437     protected void addFile(String arg) throws BadCommandLineException {
 438         addFile(arg, wsdls, ".wsdl");
 439     }
 440 
 441     private final List<InputSource> wsdls = new ArrayList<InputSource>();
 442     private final List<InputSource> schemas = new ArrayList<InputSource>();
 443     private final List<InputSource> bindingFiles = new ArrayList<InputSource>();
 444     private final List<InputSource> jaxwsCustomBindings = new ArrayList<InputSource>();
 445     private final List<InputSource> jaxbCustomBindings = new ArrayList<InputSource>();
 446     private final List<Element> handlerConfigs = new ArrayList<Element>();
 447 
 448     /**
 449      * There is supposed to be one handler chain per generated SEI.
 450      * TODO: There is possible bug, how to associate a @HandlerChain
 451      * with each port on the generated SEI. For now lets preserve the JAXWS 2.0 FCS
 452      * behaviour and generate only one @HandlerChain on the SEI
 453      */
 454     public Element getHandlerChainConfiguration(){
 455         if(handlerConfigs.size() > 0)
 456             return handlerConfigs.get(0);
 457         return null;
 458     }
 459 
 460     public void addHandlerChainConfiguration(Element config){
 461         handlerConfigs.add(config);
 462     }
 463 
 464     public InputSource[] getWSDLs() {
 465         return wsdls.toArray(new InputSource[wsdls.size()]);
 466     }
 467 
 468     public InputSource[] getSchemas() {
 469         return schemas.toArray(new InputSource[schemas.size()]);
 470     }
 471 
 472     public InputSource[] getWSDLBindings() {
 473         return jaxwsCustomBindings.toArray(new InputSource[jaxwsCustomBindings.size()]);
 474     }
 475 
 476     public InputSource[] getSchemaBindings() {
 477         return jaxbCustomBindings.toArray(new InputSource[jaxbCustomBindings.size()]);
 478     }
 479 
 480     public void addWSDL(File source) {
 481         addWSDL(fileToInputSource(source));
 482     }
 483 
 484     public void addWSDL(InputSource is) {
 485         wsdls.add(absolutize(is));
 486     }
 487 
 488     public void addSchema(File source) {
 489         addSchema(fileToInputSource(source));
 490     }
 491 
 492     public void addSchema(InputSource is) {
 493         schemas.add(is);
 494     }
 495 
 496     private InputSource fileToInputSource(File source) {
 497         try {
 498             String url = source.toURL().toExternalForm();
 499             return new InputSource(Util.escapeSpace(url));
 500         } catch (MalformedURLException e) {
 501             return new InputSource(source.getPath());
 502         }
 503     }
 504 
 505     /**
 506      * Recursively scan directories and add all XSD files in it.
 507      */
 508     public void addGrammarRecursive(File dir) {
 509         addRecursive(dir, ".wsdl", wsdls);
 510         addRecursive(dir, ".xsd", schemas);
 511     }
 512 
 513     /**
 514      * Adds a new input schema.
 515      */
 516     public void addWSDLBindFile(InputSource is) {
 517         jaxwsCustomBindings.add(new RereadInputSource(absolutize(is)));
 518     }
 519 
 520     public void addSchemmaBindFile(InputSource is) {
 521         jaxbCustomBindings.add(new RereadInputSource(absolutize(is)));
 522     }
 523 
 524     private void addRecursive(File dir, String suffix, List<InputSource> result) {
 525         File[] files = dir.listFiles();
 526         if (files == null) return; // work defensively
 527 
 528         for (File f : files) {
 529             if (f.isDirectory())
 530                 addRecursive(f, suffix, result);
 531             else if (f.getPath().endsWith(suffix))
 532                 result.add(absolutize(fileToInputSource(f)));
 533         }
 534     }
 535 
 536     private InputSource absolutize(InputSource is) {
 537         // absolutize all the system IDs in the input,
 538         // so that we can map system IDs to DOM trees.
 539         try {
 540             URL baseURL = new File(".").getCanonicalFile().toURL();
 541             is.setSystemId(new URL(baseURL, is.getSystemId()).toExternalForm());
 542         } catch (IOException e) {
 543             // ignore
 544         }
 545         return is;
 546     }
 547 
 548     public void addBindings(String name) throws BadCommandLineException {
 549         addFile(name, bindingFiles, null);
 550     }
 551 
 552     /**
 553      * Parses a token to a file (or a set of files)
 554      * and add them as {@link InputSource} to the specified list.
 555      *
 556      * @param suffix If the given token is a directory name, we do a recusive search
 557      *               and find all files that have the given suffix.
 558      */
 559     private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException {
 560         Object src;
 561         try {
 562             src = Util.getFileOrURL(name);
 563         } catch (IOException e) {
 564             throw new BadCommandLineException(WscompileMessages.WSIMPORT_NOT_A_FILE_NOR_URL(name));
 565         }
 566         if (src instanceof URL) {
 567             target.add(absolutize(new InputSource(Util.escapeSpace(((URL) src).toExternalForm()))));
 568         } else {
 569             File fsrc = (File) src;
 570             if (fsrc.isDirectory()) {
 571                 addRecursive(fsrc, suffix, target);
 572             } else {
 573                 target.add(absolutize(fileToInputSource(fsrc)));
 574             }
 575         }
 576     }
 577 
 578 
 579     /**
 580      * Exposing it as a public method to allow external tools such as NB to read from wsdl model and work on it.
 581      * TODO: WSDL model needs to be exposed - basically at tool time we need to use the runtimw wsdl model
 582      *
 583      * Binding files could be jaxws or jaxb. This method identifies jaxws and jaxb binding files and keeps them separately. jaxb binding files are given separately
 584      * to JAXB in {@link com.sun.tools.internal.ws.processor.modeler.wsdl.JAXBModelBuilder}
 585      *
 586      * @param receiver {@link ErrorReceiver}
 587      */
 588     public final void parseBindings(ErrorReceiver receiver){
 589         for (InputSource is : bindingFiles) {
 590             XMLStreamReader reader =
 591                     XMLStreamReaderFactory.create(is,true);
 592             XMLStreamReaderUtil.nextElementContent(reader);
 593             if (reader.getName().equals(JAXWSBindingsConstants.JAXWS_BINDINGS)) {
 594                 jaxwsCustomBindings.add(new RereadInputSource(is));
 595             } else if (reader.getName().equals(JAXWSBindingsConstants.JAXB_BINDINGS) ||
 596                     reader.getName().equals(new QName(SchemaConstants.NS_XSD, "schema"))) {
 597                 jaxbCustomBindings.add(new RereadInputSource(is));
 598             } else {
 599                 LocatorImpl locator = new LocatorImpl();
 600                 locator.setSystemId(reader.getLocation().getSystemId());
 601                 locator.setPublicId(reader.getLocation().getPublicId());
 602                 locator.setLineNumber(reader.getLocation().getLineNumber());
 603                 locator.setColumnNumber(reader.getLocation().getColumnNumber());
 604                 receiver.warning(locator, ConfigurationMessages.CONFIGURATION_NOT_BINDING_FILE(is.getSystemId()));
 605             }
 606         }
 607     }
 608 
 609     /**
 610      * Get extension argument
 611      */
 612     public String getExtensionOption(String argument) {
 613         return extensionOptions.get(argument);
 614     }
 615 
 616     private void parseProxy(String text) throws BadCommandLineException {
 617         int i = text.lastIndexOf('@');
 618         int j = text.lastIndexOf(':');
 619 
 620         if (i > 0) {
 621             proxyAuth = text.substring(0, i);
 622             if (j > i) {
 623                 proxyHost = text.substring(i + 1, j);
 624                 proxyPort = text.substring(j + 1);
 625             } else {
 626                 proxyHost = text.substring(i + 1);
 627                 proxyPort = "8080";
 628             }
 629         } else {
 630             //no auth info
 631             if (j < 0) {
 632                 //no port
 633                 proxyHost = text;
 634                 proxyPort = "8080";
 635             } else {
 636                 proxyHost = text.substring(0, j);
 637                 proxyPort = text.substring(j + 1);
 638             }
 639         }
 640         try {
 641             Integer.valueOf(proxyPort);
 642         } catch (NumberFormatException e) {
 643             throw new BadCommandLineException(WscompileMessages.WSIMPORT_ILLEGAL_PROXY(text));
 644         }
 645     }
 646 
 647     /**
 648      * Looks for all "META-INF/services/[className]" files and
 649      * create one instance for each class name found inside this file.
 650      */
 651     private static <T> T[] findServices(Class<T> clazz, ClassLoader classLoader) {
 652         ServiceFinder<T> serviceFinder = ServiceFinder.find(clazz, classLoader);
 653         List<T> r = new ArrayList<T>();
 654         for (T t : serviceFinder) {
 655             r.add(t);
 656         }
 657         return r.toArray((T[]) Array.newInstance(clazz, r.size()));
 658     }
 659 
 660     private static final class ByteStream extends ByteArrayOutputStream {
 661         byte[] getBuffer() {
 662                 return buf;
 663         }
 664     }
 665 
 666     private static final class RereadInputStream extends InputStream {
 667         private InputStream is;
 668         private ByteStream bs;
 669 
 670         RereadInputStream(InputStream is) {
 671                 this.is = is;
 672                 this.bs = new ByteStream();
 673         }
 674 
 675                 @Override
 676                 public int available() throws IOException {
 677                         return is.available();
 678                 }
 679 
 680                 @Override
 681                 public void close() throws IOException {
 682                         if (bs != null) {
 683                                 InputStream i = new ByteArrayInputStream(bs.getBuffer());
 684                                 bs = null;
 685                                 is.close();
 686                                 is = i;
 687                         }
 688                 }
 689 
 690                 @Override
 691                 public synchronized void mark(int readlimit) {
 692                         is.mark(readlimit);
 693                 }
 694 
 695                 @Override
 696                 public boolean markSupported() {
 697                         return is.markSupported();
 698                 }
 699 
 700                 @Override
 701                 public int read() throws IOException {
 702                         int r = is.read();
 703                         if (bs != null)
 704                                 bs.write(r);
 705                         return r;
 706                 }
 707 
 708                 @Override
 709                 public int read(byte[] b, int off, int len) throws IOException {
 710                         int r = is.read(b, off, len);
 711                         if (r > 0 && bs != null)
 712                                 bs.write(b, off, r);
 713                         return r;
 714                 }
 715 
 716                 @Override
 717                 public int read(byte[] b) throws IOException {
 718                         int r = is.read(b);
 719                         if (r > 0 && bs != null)
 720                                 bs.write(b, 0, r);
 721                         return r;
 722                 }
 723 
 724                 @Override
 725                 public synchronized void reset() throws IOException {
 726                         is.reset();
 727                 }
 728     }
 729 
 730     private static final class RereadInputSource extends InputSource {
 731         private InputSource is;
 732 
 733         RereadInputSource(InputSource is) {
 734                 this.is = is;
 735         }
 736 
 737                 @Override
 738                 public InputStream getByteStream() {
 739                         InputStream i = is.getByteStream();
 740                         if (i != null && !(i instanceof RereadInputStream)) {
 741                                 i = new RereadInputStream(i);
 742                                 is.setByteStream(i);
 743                         }
 744                         return i;
 745                 }
 746 
 747                 @Override
 748                 public Reader getCharacterStream() {
 749                         // TODO Auto-generated method stub
 750                         return is.getCharacterStream();
 751                 }
 752 
 753                 @Override
 754                 public String getEncoding() {
 755                         return is.getEncoding();
 756                 }
 757 
 758                 @Override
 759                 public String getPublicId() {
 760                         return is.getPublicId();
 761                 }
 762 
 763                 @Override
 764                 public String getSystemId() {
 765                         return is.getSystemId();
 766                 }
 767 
 768                 @Override
 769                 public void setByteStream(InputStream byteStream) {
 770                         is.setByteStream(byteStream);
 771                 }
 772 
 773                 @Override
 774                 public void setCharacterStream(Reader characterStream) {
 775                         is.setCharacterStream(characterStream);
 776                 }
 777 
 778                 @Override
 779                 public void setEncoding(String encoding) {
 780                         is.setEncoding(encoding);
 781                 }
 782 
 783                 @Override
 784                 public void setPublicId(String publicId) {
 785                         is.setPublicId(publicId);
 786                 }
 787 
 788                 @Override
 789                 public void setSystemId(String systemId) {
 790                         is.setSystemId(systemId);
 791                 }
 792     }
 793 
 794     @Override
 795     protected void disableXmlSecurity() {
 796         super.disableXmlSecurity();
 797         schemaCompiler.getOptions().disableXmlSecurity = true;
 798     }
 799 }