1 /* 2 * Copyright (c) 1997, 2010, 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.resources.ConfigurationMessages; 30 import com.sun.tools.internal.ws.resources.WscompileMessages; 31 import com.sun.tools.internal.ws.util.ForkEntityResolver; 32 import com.sun.tools.internal.ws.wsdl.document.jaxws.JAXWSBindingsConstants; 33 import com.sun.tools.internal.ws.wsdl.document.schema.SchemaConstants; 34 import com.sun.tools.internal.xjc.api.SchemaCompiler; 35 import com.sun.tools.internal.xjc.api.SpecVersion; 36 import com.sun.tools.internal.xjc.api.XJC; 37 import com.sun.tools.internal.xjc.reader.Util; 38 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; 39 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; 40 import com.sun.xml.internal.ws.util.JAXWSUtils; 41 import com.sun.xml.internal.ws.util.xml.XmlUtil; 42 import org.w3c.dom.Element; 43 import org.xml.sax.EntityResolver; 44 import org.xml.sax.InputSource; 45 import org.xml.sax.helpers.LocatorImpl; 46 47 import javax.xml.namespace.QName; 48 import javax.xml.stream.XMLStreamReader; 49 import java.io.File; 50 import java.io.IOException; 51 import java.net.Authenticator; 52 import java.net.MalformedURLException; 53 import java.net.URL; 54 import java.util.ArrayList; 55 import java.util.List; 56 57 /** 58 * @author Vivek Pandey 59 */ 60 public class WsimportOptions extends Options { 61 /** 62 * -wsdlLocation 63 */ 64 public String wsdlLocation; 65 66 /** 67 * Actually stores {@link com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver}, but the field 68 * type is made to {@link org.xml.sax.EntityResolver} so that XJC can be 69 * used even if resolver.jar is not available in the classpath. 70 */ 71 public EntityResolver entityResolver = null; 72 73 /** 74 * The -p option that should control the default Java package that 75 * will contain the generated code. Null if unspecified. 76 */ 77 public String defaultPackage = null; 78 79 /** 80 * The -clientjar option to package client artifacts as jar 81 */ 82 public String clientjar = null; 83 84 /** 85 * -XadditionalHeaders 86 */ 87 public boolean additionalHeaders; 88 89 /** 90 * Setting disableSSLHostVerification to true disables the SSL Hostname verification while fetching the wsdls. 91 * -XdisableSSLHostVerification 92 */ 93 public boolean disableSSLHostnameVerification; 94 95 /** 96 * JAXB's {@link SchemaCompiler} to be used for handling the schema portion. 97 * This object is also configured through options. 98 */ 99 private SchemaCompiler schemaCompiler = XJC.createSchemaCompiler(); 100 101 /** 102 * Authentication file 103 */ 104 public File authFile; 105 106 public JCodeModel getCodeModel() { 107 if(codeModel == null) 108 codeModel = new JCodeModel(); 109 return codeModel; 110 } 111 112 public SchemaCompiler getSchemaCompiler() { 113 schemaCompiler.setTargetVersion(SpecVersion.parse(target.getVersion())); 114 if(entityResolver != null) { 115 //set if its not null so as not to override catalog option specified via xjc args 116 schemaCompiler.setEntityResolver(entityResolver); 117 } 118 return schemaCompiler; 119 } 120 121 public void setCodeModel(JCodeModel codeModel) { 122 this.codeModel = codeModel; 123 } 124 125 private JCodeModel codeModel; 126 127 /** 128 * This captures jars passed on the commandline and passes them to XJC and puts them in the classpath for compilation 129 */ 130 public List<String> cmdlineJars = new ArrayList<String>(); 131 132 /** 133 * Parses arguments and fill fields of this object. 134 * 135 * @exception BadCommandLineException 136 * thrown when there's a problem in the command-line arguments 137 */ 138 @Override 139 public final void parseArguments( String[] args ) throws BadCommandLineException { 140 141 for (int i = 0; i < args.length; i++) { 142 if(args[i].length()==0) 143 throw new BadCommandLineException(); 144 if (args[i].charAt(0) == '-') { 145 int j = parseArguments(args,i); 146 if(j==0) 147 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i])); 148 i += (j-1); 149 } else { 150 if(args[i].endsWith(".jar")) { 151 152 try { 153 cmdlineJars.add(args[i]); 154 schemaCompiler.getOptions().scanEpisodeFile(new File(args[i])); 155 156 } catch (com.sun.tools.internal.xjc.BadCommandLineException e) { 157 //Driver.usage(jaxbOptions,false); 158 throw new BadCommandLineException(e.getMessage(), e); 159 } 160 } else{ 161 addFile(args[i]); 162 } 163 } 164 } 165 if(destDir == null) 166 destDir = new File("."); 167 if(sourceDir == null) 168 sourceDir = destDir; 169 } 170 171 /** -Xno-addressing-databinding option to disable addressing namespace data binding. This is 172 * experimental switch and will be working as a temporary workaround till 173 * jaxb can provide a better way to selelctively disable compiling of an 174 * schema component. 175 * **/ 176 public boolean noAddressingBbinding; 177 178 @Override 179 public int parseArguments(String[] args, int i) throws BadCommandLineException { 180 int j = super.parseArguments(args ,i); 181 if(j>0) return j; // understood by the super class 182 183 if (args[i].equals("-b")) { 184 addBindings(requireArgument("-b", args, ++i)); 185 return 2; 186 } else if (args[i].equals("-wsdllocation")) { 187 wsdlLocation = requireArgument("-wsdllocation", args, ++i); 188 return 2; 189 } else if (args[i].equals("-XadditionalHeaders")) { 190 additionalHeaders = true; 191 return 1; 192 } else if (args[i].equals("-XdisableSSLHostnameVerification")) { 193 disableSSLHostnameVerification = true; 194 return 1; 195 } else if (args[i].equals("-p")) { 196 defaultPackage = requireArgument("-p", args, ++i); 197 return 2; 198 } else if (args[i].equals("-catalog")) { 199 String catalog = requireArgument("-catalog", args, ++i); 200 try { 201 if (entityResolver == null) { 202 if (catalog != null && catalog.length() > 0) 203 entityResolver = XmlUtil.createEntityResolver(JAXWSUtils.getFileOrURL(JAXWSUtils.absolutize(Util.escapeSpace(catalog)))); 204 } else if (catalog != null && catalog.length() > 0) { 205 EntityResolver er = XmlUtil.createEntityResolver(JAXWSUtils.getFileOrURL(JAXWSUtils.absolutize(Util.escapeSpace(catalog)))); 206 entityResolver = new ForkEntityResolver(er, entityResolver); 207 } 208 } catch (IOException e) { 209 throw new BadCommandLineException(WscompileMessages.WSIMPORT_FAILED_TO_PARSE(catalog, e.getMessage())); 210 } 211 return 2; 212 } else if (args[i].startsWith("-httpproxy:")) { 213 String value = args[i].substring(11); 214 if (value.length() == 0) { 215 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i])); 216 } 217 int index = value.indexOf(':'); 218 if (index == -1) { 219 System.setProperty("proxySet", "true"); 220 System.setProperty("proxyHost", value); 221 System.setProperty("proxyPort", "8080"); 222 } else { 223 System.setProperty("proxySet", "true"); 224 System.setProperty("proxyHost", value.substring(0, index)); 225 System.setProperty("proxyPort", value.substring(index + 1)); 226 } 227 return 1; 228 } else if (args[i].equals("-Xno-addressing-databinding")) { 229 noAddressingBbinding = true; 230 return 1; 231 } else if (args[i].startsWith("-B")) { 232 // JAXB option pass through. 233 String[] subCmd = new String[args.length-i]; 234 System.arraycopy(args,i,subCmd,0,subCmd.length); 235 subCmd[0] = subCmd[0].substring(2); // trim off the first "-B" 236 237 com.sun.tools.internal.xjc.Options jaxbOptions = schemaCompiler.getOptions(); 238 try { 239 int r = jaxbOptions.parseArgument(subCmd, 0); 240 if(r==0) { 241 //Driver.usage(jaxbOptions,false); 242 throw new BadCommandLineException(WscompileMessages.WSIMPORT_NO_SUCH_JAXB_OPTION(subCmd[0])); 243 } 244 return r; 245 } catch (com.sun.tools.internal.xjc.BadCommandLineException e) { 246 //Driver.usage(jaxbOptions,false); 247 throw new BadCommandLineException(e.getMessage(),e); 248 } 249 } else if (args[i].equals("-Xauthfile")) { 250 String authfile = requireArgument("-Xauthfile", args, ++i); 251 authFile = new File(authfile); 252 return 2; 253 } else if (args[i].equals("-clientjar")) { 254 clientjar = requireArgument("-clientjar", args, ++i); 255 return 2; 256 } 257 258 return 0; // what's this option? 259 } 260 261 public void validate() throws BadCommandLineException { 262 if (wsdls.isEmpty()) { 263 throw new BadCommandLineException(WscompileMessages.WSIMPORT_MISSING_FILE()); 264 } 265 266 if(wsdlLocation !=null && clientjar != null) { 267 throw new BadCommandLineException(WscompileMessages.WSIMPORT_WSDLLOCATION_CLIENTJAR()); 268 } 269 if(wsdlLocation == null){ 270 wsdlLocation = wsdls.get(0).getSystemId(); 271 } 272 273 274 } 275 276 @Override 277 protected void addFile(String arg) throws BadCommandLineException { 278 addFile(arg, wsdls, ".wsdl"); 279 } 280 281 private final List<InputSource> wsdls = new ArrayList<InputSource>(); 282 private final List<InputSource> schemas = new ArrayList<InputSource>(); 283 private final List<InputSource> bindingFiles = new ArrayList<InputSource>(); 284 private final List<InputSource> jaxwsCustomBindings = new ArrayList<InputSource>(); 285 private final List<InputSource> jaxbCustomBindings = new ArrayList<InputSource>(); 286 private final List<Element> handlerConfigs = new ArrayList<Element>(); 287 288 /** 289 * There is supposed to be one handler chain per generated SEI. 290 * TODO: There is possible bug, how to associate a @HandlerChain 291 * with each port on the generated SEI. For now lets preserve the JAXWS 2.0 FCS 292 * behaviour and generate only one @HandlerChain on the SEI 293 */ 294 public Element getHandlerChainConfiguration(){ 295 if(handlerConfigs.size() > 0) 296 return handlerConfigs.get(0); 297 return null; 298 } 299 300 public void addHandlerChainConfiguration(Element config){ 301 handlerConfigs.add(config); 302 } 303 304 public InputSource[] getWSDLs() { 305 return wsdls.toArray(new InputSource[wsdls.size()]); 306 } 307 308 public InputSource[] getSchemas() { 309 return schemas.toArray(new InputSource[schemas.size()]); 310 } 311 312 public InputSource[] getWSDLBindings() { 313 return jaxwsCustomBindings.toArray(new InputSource[jaxwsCustomBindings.size()]); 314 } 315 316 public InputSource[] getSchemaBindings() { 317 return jaxbCustomBindings.toArray(new InputSource[jaxbCustomBindings.size()]); 318 } 319 320 public void addWSDL(File source) { 321 addWSDL(fileToInputSource(source)); 322 } 323 324 public void addWSDL(InputSource is) { 325 wsdls.add(absolutize(is)); 326 } 327 328 public void addSchema(File source) { 329 addSchema(fileToInputSource(source)); 330 } 331 332 public void addSchema(InputSource is) { 333 schemas.add(is); 334 } 335 336 private InputSource fileToInputSource(File source) { 337 try { 338 String url = source.toURL().toExternalForm(); 339 return new InputSource(Util.escapeSpace(url)); 340 } catch (MalformedURLException e) { 341 return new InputSource(source.getPath()); 342 } 343 } 344 345 /** 346 * Recursively scan directories and add all XSD files in it. 347 */ 348 public void addGrammarRecursive(File dir) { 349 addRecursive(dir, ".wsdl", wsdls); 350 addRecursive(dir, ".xsd", schemas); 351 } 352 353 /** 354 * Adds a new input schema. 355 */ 356 public void addWSDLBindFile(InputSource is) { 357 jaxwsCustomBindings.add(absolutize(is)); 358 } 359 360 public void addSchemmaBindFile(InputSource is) { 361 jaxbCustomBindings.add(absolutize(is)); 362 } 363 364 private void addRecursive(File dir, String suffix, List<InputSource> result) { 365 File[] files = dir.listFiles(); 366 if (files == null) return; // work defensively 367 368 for (File f : files) { 369 if (f.isDirectory()) 370 addRecursive(f, suffix, result); 371 else if (f.getPath().endsWith(suffix)) 372 result.add(absolutize(fileToInputSource(f))); 373 } 374 } 375 376 private InputSource absolutize(InputSource is) { 377 // absolutize all the system IDs in the input, 378 // so that we can map system IDs to DOM trees. 379 try { 380 URL baseURL = new File(".").getCanonicalFile().toURL(); 381 is.setSystemId(new URL(baseURL, is.getSystemId()).toExternalForm()); 382 } catch (IOException e) { 383 // ignore 384 } 385 return is; 386 } 387 388 public void addBindings(String name) throws BadCommandLineException { 389 addFile(name, bindingFiles, null); 390 } 391 392 /** 393 * Parses a token to a file (or a set of files) 394 * and add them as {@link InputSource} to the specified list. 395 * 396 * @param suffix If the given token is a directory name, we do a recusive search 397 * and find all files that have the given suffix. 398 */ 399 private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException { 400 Object src; 401 try { 402 src = Util.getFileOrURL(name); 403 } catch (IOException e) { 404 throw new BadCommandLineException(WscompileMessages.WSIMPORT_NOT_A_FILE_NOR_URL(name)); 405 } 406 if (src instanceof URL) { 407 target.add(absolutize(new InputSource(Util.escapeSpace(((URL) src).toExternalForm())))); 408 } else { 409 File fsrc = (File) src; 410 if (fsrc.isDirectory()) { 411 addRecursive(fsrc, suffix, target); 412 } else { 413 target.add(absolutize(fileToInputSource(fsrc))); 414 } 415 } 416 } 417 418 419 /** 420 * Exposing it as a public method to allow external tools such as NB to read from wsdl model and work on it. 421 * TODO: WSDL model needs to be exposed - basically at tool time we need to use the runtimw wsdl model 422 * 423 * 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 424 * to JAXB in {@link com.sun.tools.internal.ws.processor.modeler.wsdl.JAXBModelBuilder} 425 * 426 * @param receiver {@link ErrorReceiver} 427 */ 428 public final void parseBindings(ErrorReceiver receiver){ 429 for (InputSource is : bindingFiles) { 430 XMLStreamReader reader = 431 XMLStreamReaderFactory.create(is,true); 432 XMLStreamReaderUtil.nextElementContent(reader); 433 if (reader.getName().equals(JAXWSBindingsConstants.JAXWS_BINDINGS)) { 434 jaxwsCustomBindings.add(is); 435 } else if (reader.getName().equals(JAXWSBindingsConstants.JAXB_BINDINGS) || 436 reader.getName().equals(new QName(SchemaConstants.NS_XSD, "schema"))) { 437 jaxbCustomBindings.add(is); 438 } else { 439 LocatorImpl locator = new LocatorImpl(); 440 locator.setSystemId(reader.getLocation().getSystemId()); 441 locator.setPublicId(reader.getLocation().getPublicId()); 442 locator.setLineNumber(reader.getLocation().getLineNumber()); 443 locator.setColumnNumber(reader.getLocation().getColumnNumber()); 444 receiver.warning(locator, ConfigurationMessages.CONFIGURATION_NOT_BINDING_FILE(is.getSystemId())); 445 } 446 } 447 } 448 }