1 /* 2 * Copyright (c) 1997, 2013, 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.xml.internal.ws.wsdl.writer; 27 28 29 import static com.sun.xml.internal.bind.v2.schemagen.Util.*; 30 31 import com.oracle.webservices.internal.api.databinding.WSDLResolver; 32 33 import com.sun.xml.internal.txw2.TXW; 34 import com.sun.xml.internal.txw2.TypedXmlWriter; 35 import com.sun.xml.internal.txw2.output.ResultFactory; 36 import com.sun.xml.internal.txw2.output.XmlSerializer; 37 import com.sun.xml.internal.txw2.output.TXWResult; 38 import com.sun.xml.internal.ws.api.SOAPVersion; 39 import com.sun.xml.internal.ws.api.WSBinding; 40 import com.sun.xml.internal.ws.api.model.JavaMethod; 41 import com.sun.xml.internal.ws.api.model.MEP; 42 import com.sun.xml.internal.ws.api.model.ParameterBinding; 43 import com.sun.xml.internal.ws.api.model.SEIModel; 44 import com.sun.xml.internal.ws.api.model.soap.SOAPBinding; 45 import com.sun.xml.internal.ws.api.server.Container; 46 import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension; 47 import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGenExtnContext; 48 import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; 49 import com.sun.xml.internal.ws.model.CheckedExceptionImpl; 50 import com.sun.xml.internal.ws.model.JavaMethodImpl; 51 import com.sun.xml.internal.ws.model.ParameterImpl; 52 import com.sun.xml.internal.ws.model.WrapperParameter; 53 import com.sun.xml.internal.ws.util.xml.XmlUtil; 54 import com.sun.xml.internal.ws.wsdl.parser.SOAPConstants; 55 import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; 56 import com.sun.xml.internal.ws.wsdl.writer.document.Binding; 57 import com.sun.xml.internal.ws.wsdl.writer.document.BindingOperationType; 58 import com.sun.xml.internal.ws.wsdl.writer.document.Definitions; 59 import com.sun.xml.internal.ws.wsdl.writer.document.Fault; 60 import com.sun.xml.internal.ws.wsdl.writer.document.FaultType; 61 import com.sun.xml.internal.ws.wsdl.writer.document.Import; 62 import com.sun.xml.internal.ws.wsdl.writer.document.Message; 63 import com.sun.xml.internal.ws.wsdl.writer.document.Operation; 64 import com.sun.xml.internal.ws.wsdl.writer.document.ParamType; 65 import com.sun.xml.internal.ws.wsdl.writer.document.Port; 66 import com.sun.xml.internal.ws.wsdl.writer.document.PortType; 67 import com.sun.xml.internal.ws.wsdl.writer.document.Service; 68 import com.sun.xml.internal.ws.wsdl.writer.document.Types; 69 import com.sun.xml.internal.ws.wsdl.writer.document.soap.Body; 70 import com.sun.xml.internal.ws.wsdl.writer.document.soap.BodyType; 71 import com.sun.xml.internal.ws.wsdl.writer.document.soap.Header; 72 import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPAddress; 73 import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPFault; 74 import com.sun.xml.internal.ws.wsdl.writer.document.xsd.Schema; 75 import com.sun.xml.internal.ws.spi.db.BindingContext; 76 import com.sun.xml.internal.ws.spi.db.BindingHelper; 77 import com.sun.xml.internal.ws.spi.db.TypeInfo; 78 import com.sun.xml.internal.ws.spi.db.WrapperComposite; 79 import com.sun.xml.internal.ws.util.RuntimeVersion; 80 import com.sun.xml.internal.ws.policy.jaxws.PolicyWSDLGeneratorExtension; 81 import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants; 82 import com.sun.xml.internal.bind.v2.schemagen.xmlschema.Element; 83 import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ComplexType; 84 import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ExplicitGroup; 85 import com.sun.xml.internal.bind.v2.schemagen.xmlschema.LocalElement; 86 87 import javax.jws.soap.SOAPBinding.Style; 88 import javax.jws.soap.SOAPBinding.Use; 89 import javax.xml.bind.SchemaOutputResolver; 90 import javax.xml.namespace.QName; 91 import javax.xml.transform.Result; 92 import javax.xml.transform.Transformer; 93 import javax.xml.transform.TransformerConfigurationException; 94 import javax.xml.transform.TransformerException; 95 import javax.xml.transform.TransformerFactory; 96 import javax.xml.transform.dom.DOMResult; 97 import javax.xml.transform.dom.DOMSource; 98 import javax.xml.transform.sax.SAXResult; 99 import javax.xml.ws.Holder; 100 import javax.xml.ws.WebServiceException; 101 102 import org.w3c.dom.Document; 103 104 import java.io.IOException; 105 import java.net.URI; 106 import java.net.URISyntaxException; 107 import java.util.ArrayList; 108 import java.util.HashMap; 109 import java.util.HashSet; 110 import java.util.Iterator; 111 import java.util.List; 112 import java.util.Set; 113 114 115 /** 116 * Class used to generate WSDLs from a {@link SEIModel}. 117 * 118 * @author WS Development Team 119 */ 120 public class WSDLGenerator { 121 private JAXWSOutputSchemaResolver resolver; 122 private WSDLResolver wsdlResolver = null; 123 private AbstractSEIModelImpl model; 124 private Definitions serviceDefinitions; 125 private Definitions portDefinitions; 126 private Types types; 127 /** 128 * Constant String for ".wsdl" 129 */ 130 private static final String DOT_WSDL = ".wsdl"; 131 /** 132 * Constant String appended to response message names 133 */ 134 private static final String RESPONSE = "Response"; 135 /** 136 * constant String used for part name for wrapped request messages 137 */ 138 private static final String PARAMETERS = "parameters"; 139 /** 140 * the part name for unwrappable response messages 141 */ 142 private static final String RESULT = "parameters"; 143 /** 144 * the part name for response messages that are not unwrappable 145 */ 146 private static final String UNWRAPPABLE_RESULT = "result"; 147 /** 148 * The WSDL namespace 149 */ 150 private static final String WSDL_NAMESPACE = WSDLConstants.NS_WSDL; 151 152 /** 153 * the XSD namespace 154 */ 155 private static final String XSD_NAMESPACE = SOAPNamespaceConstants.XSD; 156 /** 157 * the namespace prefix to use for the XSD namespace 158 */ 159 private static final String XSD_PREFIX = "xsd"; 160 /** 161 * The SOAP 1.1 namespace 162 */ 163 private static final String SOAP11_NAMESPACE = SOAPConstants.NS_WSDL_SOAP; 164 /** 165 * The SOAP 1.2 namespace 166 */ 167 private static final String SOAP12_NAMESPACE = SOAPConstants.NS_WSDL_SOAP12; 168 /** 169 * The namespace prefix to use for the SOAP 1.1 namespace 170 */ 171 private static final String SOAP_PREFIX = "soap"; 172 /** 173 * The namespace prefix to use for the SOAP 1.2 namespace 174 */ 175 private static final String SOAP12_PREFIX = "soap12"; 176 /** 177 * The namespace prefix to use for the targetNamespace 178 */ 179 private static final String TNS_PREFIX = "tns"; 180 181 /** 182 * Constant String "document" used to specify <code>document</code> style 183 * soapBindings 184 */ 185 private static final String DOCUMENT = "document"; 186 /** 187 * Constant String "rpc" used to specify <code>rpc</code> style 188 * soapBindings 189 */ 190 private static final String RPC = "rpc"; 191 /** 192 * Constant String "literal" used to create <code>literal</code> use binddings 193 */ 194 private static final String LITERAL = "literal"; 195 /** 196 * Constant String to flag the URL to replace at runtime for the endpoint 197 */ 198 private static final String REPLACE_WITH_ACTUAL_URL = "REPLACE_WITH_ACTUAL_URL"; 199 private Set<QName> processedExceptions = new HashSet<QName>(); 200 private WSBinding binding; 201 private String wsdlLocation; 202 private String portWSDLID; 203 private String schemaPrefix; 204 private WSDLGeneratorExtension extension; 205 List<WSDLGeneratorExtension> extensionHandlers; 206 207 private String endpointAddress = REPLACE_WITH_ACTUAL_URL; 208 private Container container; 209 private final Class implType; 210 211 private boolean inlineSchemas; // TODO 212 private final boolean disableXmlSecurity; 213 214 /** 215 * Creates the WSDLGenerator 216 * @param model The {@link AbstractSEIModelImpl} used to generate the WSDL 217 * @param wsdlResolver The {@link WSDLResolver} to use resovle names while generating the WSDL 218 * @param binding specifies which {@link javax.xml.ws.BindingType} to generate 219 * @param extensions an array {@link WSDLGeneratorExtension} that will 220 * be invoked to generate WSDL extensions 221 */ WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, Class implType, boolean inlineSchemas, WSDLGeneratorExtension... extensions)222 public WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, 223 Class implType, boolean inlineSchemas, WSDLGeneratorExtension... extensions) { 224 this(model, wsdlResolver, binding, container, implType, inlineSchemas, false, extensions); 225 } 226 227 /** 228 * Creates the WSDLGenerator 229 * @param model The {@link AbstractSEIModelImpl} used to generate the WSDL 230 * @param wsdlResolver The {@link WSDLResolver} to use resovle names while generating the WSDL 231 * @param binding specifies which {@link javax.xml.ws.BindingType} to generate 232 * @param disableXmlSecurity specifies whether to disable the secure xml processing feature 233 * @param extensions an array {@link WSDLGeneratorExtension} that will 234 * be invoked to generate WSDL extensions 235 */ WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, Class implType, boolean inlineSchemas, boolean disableXmlSecurity, WSDLGeneratorExtension... extensions)236 public WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, 237 Class implType, boolean inlineSchemas, boolean disableXmlSecurity, 238 WSDLGeneratorExtension... extensions) { 239 240 this.model = model; 241 resolver = new JAXWSOutputSchemaResolver(); 242 this.wsdlResolver = wsdlResolver; 243 this.binding = binding; 244 this.container = container; 245 this.implType = implType; 246 extensionHandlers = new ArrayList<WSDLGeneratorExtension>(); 247 this.inlineSchemas = inlineSchemas; 248 this.disableXmlSecurity = disableXmlSecurity; 249 250 // register handlers for default extensions 251 register(new W3CAddressingWSDLGeneratorExtension()); 252 register(new W3CAddressingMetadataWSDLGeneratorExtension()); 253 register(new PolicyWSDLGeneratorExtension()); 254 255 if (container != null) { // on server 256 WSDLGeneratorExtension[] wsdlGeneratorExtensions = container.getSPI(WSDLGeneratorExtension[].class); 257 if (wsdlGeneratorExtensions != null) { 258 for (WSDLGeneratorExtension wsdlGeneratorExtension : wsdlGeneratorExtensions) { 259 register(wsdlGeneratorExtension); 260 } 261 } 262 } 263 264 for (WSDLGeneratorExtension w : extensions) 265 register(w); 266 267 this.extension = new WSDLGeneratorExtensionFacade(extensionHandlers.toArray(new WSDLGeneratorExtension[0])); 268 } 269 270 /** 271 * Sets the endpoint address string to be written. 272 * Defaults to {@link #REPLACE_WITH_ACTUAL_URL}. 273 * 274 * @param address wsdl:port/soap:address/[@location] value 275 */ setEndpointAddress(String address)276 public void setEndpointAddress(String address) { 277 this.endpointAddress = address; 278 } 279 mangleName(String name)280 protected String mangleName(String name) { 281 return BindingHelper.mangleNameToClassName(name); 282 } 283 284 /** 285 * Performes the actual WSDL generation 286 */ doGeneration()287 public void doGeneration() { 288 XmlSerializer serviceWriter; 289 XmlSerializer portWriter = null; 290 String fileName = mangleName(model.getServiceQName().getLocalPart()); 291 Result result = wsdlResolver.getWSDL(fileName + DOT_WSDL); 292 wsdlLocation = result.getSystemId(); 293 serviceWriter = new CommentFilter(ResultFactory.createSerializer(result)); 294 if (model.getServiceQName().getNamespaceURI().equals(model.getTargetNamespace())) { 295 portWriter = serviceWriter; 296 schemaPrefix = fileName + "_"; 297 } else { 298 String wsdlName = mangleName(model.getPortTypeName().getLocalPart()); 299 if (wsdlName.equals(fileName)) 300 wsdlName += "PortType"; 301 Holder<String> absWSDLName = new Holder<String>(); 302 absWSDLName.value = wsdlName + DOT_WSDL; 303 result = wsdlResolver.getAbstractWSDL(absWSDLName); 304 305 if (result != null) { 306 portWSDLID = result.getSystemId(); 307 if (portWSDLID.equals(wsdlLocation)) { 308 portWriter = serviceWriter; 309 } else { 310 portWriter = new CommentFilter(ResultFactory.createSerializer(result)); 311 } 312 } else { 313 portWSDLID = absWSDLName.value; 314 } 315 schemaPrefix = new java.io.File(portWSDLID).getName(); 316 int idx = schemaPrefix.lastIndexOf('.'); 317 if (idx > 0) 318 schemaPrefix = schemaPrefix.substring(0, idx); 319 schemaPrefix = mangleName(schemaPrefix) + "_"; 320 } 321 generateDocument(serviceWriter, portWriter); 322 } 323 324 /** 325 * Writing directly to XmlSerializer is a problem, since it doesn't suppress 326 * xml declaration. Creating filter so that comment is written before TXW writes 327 * anything in the WSDL. 328 */ 329 private static class CommentFilter implements XmlSerializer { 330 final XmlSerializer serializer; 331 private static final String VERSION_COMMENT = 332 " Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is " + RuntimeVersion.VERSION + ". "; 333 CommentFilter(XmlSerializer serializer)334 CommentFilter(XmlSerializer serializer) { 335 this.serializer = serializer; 336 } 337 338 @Override startDocument()339 public void startDocument() { 340 serializer.startDocument(); 341 comment(new StringBuilder(VERSION_COMMENT)); 342 text(new StringBuilder("\n")); 343 } 344 345 @Override beginStartTag(String uri, String localName, String prefix)346 public void beginStartTag(String uri, String localName, String prefix) { 347 serializer.beginStartTag(uri, localName, prefix); 348 } 349 350 @Override writeAttribute(String uri, String localName, String prefix, StringBuilder value)351 public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) { 352 serializer.writeAttribute(uri, localName, prefix, value); 353 } 354 355 @Override writeXmlns(String prefix, String uri)356 public void writeXmlns(String prefix, String uri) { 357 serializer.writeXmlns(prefix, uri); 358 } 359 360 @Override endStartTag(String uri, String localName, String prefix)361 public void endStartTag(String uri, String localName, String prefix) { 362 serializer.endStartTag(uri, localName, prefix); 363 } 364 365 @Override endTag()366 public void endTag() { 367 serializer.endTag(); 368 } 369 370 @Override text(StringBuilder text)371 public void text(StringBuilder text) { 372 serializer.text(text); 373 } 374 375 @Override cdata(StringBuilder text)376 public void cdata(StringBuilder text) { 377 serializer.cdata(text); 378 } 379 380 @Override comment(StringBuilder comment)381 public void comment(StringBuilder comment) { 382 serializer.comment(comment); 383 } 384 385 @Override endDocument()386 public void endDocument() { 387 serializer.endDocument(); 388 } 389 390 @Override flush()391 public void flush() { 392 serializer.flush(); 393 } 394 395 } 396 generateDocument(XmlSerializer serviceStream, XmlSerializer portStream)397 private void generateDocument(XmlSerializer serviceStream, XmlSerializer portStream) { 398 serviceDefinitions = TXW.create(Definitions.class, serviceStream); 399 serviceDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); 400 serviceDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); 401 serviceDefinitions.targetNamespace(model.getServiceQName().getNamespaceURI()); 402 serviceDefinitions._namespace(model.getServiceQName().getNamespaceURI(), TNS_PREFIX); 403 if (binding.getSOAPVersion() == SOAPVersion.SOAP_12) 404 serviceDefinitions._namespace(SOAP12_NAMESPACE, SOAP12_PREFIX); 405 else 406 serviceDefinitions._namespace(SOAP11_NAMESPACE, SOAP_PREFIX); 407 serviceDefinitions.name(model.getServiceQName().getLocalPart()); 408 WSDLGenExtnContext serviceCtx = new WSDLGenExtnContext(serviceDefinitions, model, binding, container, implType); 409 extension.start(serviceCtx); 410 if (serviceStream != portStream && portStream != null) { 411 // generate an abstract and concrete wsdl 412 portDefinitions = TXW.create(Definitions.class, portStream); 413 portDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); 414 portDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); 415 if (model.getTargetNamespace() != null) { 416 portDefinitions.targetNamespace(model.getTargetNamespace()); 417 portDefinitions._namespace(model.getTargetNamespace(), TNS_PREFIX); 418 } 419 420 String schemaLoc = relativize(portWSDLID, wsdlLocation); 421 Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); 422 _import.location(schemaLoc); 423 } else if (portStream != null) { 424 // abstract and concrete are the same 425 portDefinitions = serviceDefinitions; 426 } else { 427 // import a provided abstract wsdl 428 String schemaLoc = relativize(portWSDLID, wsdlLocation); 429 Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); 430 _import.location(schemaLoc); 431 } 432 extension.addDefinitionsExtension(serviceDefinitions); 433 434 if (portDefinitions != null) { 435 generateTypes(); 436 generateMessages(); 437 generatePortType(); 438 } 439 generateBinding(); 440 generateService(); 441 //Give a chance to WSDLGeneratorExtensions to write stuff before closing </wsdl:defintions> 442 extension.end(serviceCtx); 443 serviceDefinitions.commit(); 444 if (portDefinitions != null && portDefinitions != serviceDefinitions) 445 portDefinitions.commit(); 446 } 447 448 449 /** 450 * Generates the types section of the WSDL 451 */ generateTypes()452 protected void generateTypes() { 453 types = portDefinitions.types(); 454 if (model.getBindingContext() != null) { 455 if (inlineSchemas && model.getBindingContext().getClass().getName().indexOf("glassfish") == -1) { 456 resolver.nonGlassfishSchemas = new ArrayList<DOMResult>(); 457 } 458 try { 459 model.getBindingContext().generateSchema(resolver); 460 } catch (IOException e) { 461 // TODO locallize and wrap this 462 throw new WebServiceException(e.getMessage()); 463 } 464 } 465 if (resolver.nonGlassfishSchemas != null) { 466 TransformerFactory tf = XmlUtil.newTransformerFactory(!disableXmlSecurity); 467 try { 468 Transformer t = tf.newTransformer(); 469 for (DOMResult xsd : resolver.nonGlassfishSchemas) { 470 Document doc = (Document) xsd.getNode(); 471 SAXResult sax = new SAXResult(new TXWContentHandler(types)); 472 t.transform(new DOMSource(doc.getDocumentElement()), sax); 473 } 474 } catch (TransformerConfigurationException e) { 475 throw new WebServiceException(e.getMessage(), e); 476 } catch (TransformerException e) { 477 throw new WebServiceException(e.getMessage(), e); 478 } 479 } 480 generateWrappers(); 481 } 482 generateWrappers()483 void generateWrappers() { 484 List<WrapperParameter> wrappers = new ArrayList<WrapperParameter>(); 485 for (JavaMethodImpl method : model.getJavaMethods()) { 486 if(method.getBinding().isRpcLit()) continue; 487 for (ParameterImpl p : method.getRequestParameters()) { 488 if (p instanceof WrapperParameter) { 489 if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { 490 wrappers.add((WrapperParameter)p); 491 } 492 } 493 } 494 for (ParameterImpl p : method.getResponseParameters()) { 495 if (p instanceof WrapperParameter) { 496 if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { 497 wrappers.add((WrapperParameter)p); 498 } 499 } 500 } 501 } 502 if (wrappers.isEmpty()) return; 503 HashMap<String, Schema> xsds = new HashMap<String, Schema>(); 504 for(WrapperParameter wp : wrappers) { 505 String tns = wp.getName().getNamespaceURI(); 506 Schema xsd = xsds.get(tns); 507 if (xsd == null) { 508 xsd = types.schema(); 509 xsd.targetNamespace(tns); 510 xsds.put(tns, xsd); 511 } 512 Element e = xsd._element(Element.class); 513 e._attribute("name", wp.getName().getLocalPart()); 514 e.type(wp.getName()); 515 ComplexType ct = xsd._element(ComplexType.class); 516 ct._attribute("name", wp.getName().getLocalPart()); 517 ExplicitGroup sq = ct.sequence(); 518 for (ParameterImpl p : wp.getWrapperChildren() ) { 519 if (p.getBinding().isBody()) { 520 LocalElement le = sq.element(); 521 le._attribute("name", p.getName().getLocalPart()); 522 TypeInfo typeInfo = p.getItemType(); 523 boolean repeatedElement = false; 524 if (typeInfo == null) { 525 typeInfo = p.getTypeInfo(); 526 } else { 527 repeatedElement = true; 528 } 529 QName type = model.getBindingContext().getTypeName(typeInfo); 530 le.type(type); 531 if (repeatedElement) { 532 le.minOccurs(0); 533 le.maxOccurs("unbounded"); 534 } 535 } 536 } 537 } 538 } 539 540 /** 541 * Generates the WSDL messages 542 */ generateMessages()543 protected void generateMessages() { 544 for (JavaMethodImpl method : model.getJavaMethods()) { 545 generateSOAPMessages(method, method.getBinding()); 546 } 547 } 548 549 /** 550 * Generates messages for a SOAPBinding 551 * @param method The {@link JavaMethod} to generate messages for 552 * @param binding The {@link com.sun.xml.internal.ws.api.model.soap.SOAPBinding} to add the generated messages to 553 */ generateSOAPMessages(JavaMethodImpl method, com.sun.xml.internal.ws.api.model.soap.SOAPBinding binding)554 protected void generateSOAPMessages(JavaMethodImpl method, com.sun.xml.internal.ws.api.model.soap.SOAPBinding binding) { 555 boolean isDoclit = binding.isDocLit(); 556 // Message message = portDefinitions.message().name(method.getOperation().getName().getLocalPart()); 557 Message message = portDefinitions.message().name(method.getRequestMessageName()); 558 extension.addInputMessageExtension(message, method); 559 com.sun.xml.internal.ws.wsdl.writer.document.Part part; 560 BindingContext jaxbContext = model.getBindingContext(); 561 boolean unwrappable = true; 562 for (ParameterImpl param : method.getRequestParameters()) { 563 if (isDoclit) { 564 if (isHeaderParameter(param)) 565 unwrappable = false; 566 567 part = message.part().name(param.getPartName()); 568 part.element(param.getName()); 569 } else { 570 if (param.isWrapperStyle()) { 571 for (ParameterImpl childParam : ((WrapperParameter) param).getWrapperChildren()) { 572 part = message.part().name(childParam.getPartName()); 573 part.type(jaxbContext.getTypeName(childParam.getXMLBridge().getTypeInfo())); 574 } 575 } else { 576 part = message.part().name(param.getPartName()); 577 part.element(param.getName()); 578 } 579 } 580 } 581 if (method.getMEP() != MEP.ONE_WAY) { 582 message = portDefinitions.message().name(method.getResponseMessageName()); 583 extension.addOutputMessageExtension(message, method); 584 585 for (ParameterImpl param : method.getResponseParameters()) { 586 if (isDoclit) { 587 part = message.part().name(param.getPartName()); 588 part.element(param.getName()); 589 590 } else { 591 if (param.isWrapperStyle()) { 592 for (ParameterImpl childParam : ((WrapperParameter) param).getWrapperChildren()) { 593 part = message.part().name(childParam.getPartName()); 594 part.type(jaxbContext.getTypeName(childParam.getXMLBridge().getTypeInfo())); 595 } 596 } else { 597 part = message.part().name(param.getPartName()); 598 part.element(param.getName()); 599 } 600 } 601 } 602 } 603 for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { 604 QName tagName = exception.getDetailType().tagName; 605 String messageName = exception.getMessageName(); 606 QName messageQName = new QName(model.getTargetNamespace(), messageName); 607 if (processedExceptions.contains(messageQName)) 608 continue; 609 message = portDefinitions.message().name(messageName); 610 611 extension.addFaultMessageExtension(message, method, exception); 612 part = message.part().name("fault");//tagName.getLocalPart()); 613 part.element(tagName); 614 processedExceptions.add(messageQName); 615 } 616 } 617 618 /** 619 * Generates the WSDL portType 620 */ generatePortType()621 protected void generatePortType() { 622 623 PortType portType = portDefinitions.portType().name(model.getPortTypeName().getLocalPart()); 624 extension.addPortTypeExtension(portType); 625 for (JavaMethodImpl method : model.getJavaMethods()) { 626 Operation operation = portType.operation().name(method.getOperationName()); 627 generateParameterOrder(operation, method); 628 extension.addOperationExtension(operation, method); 629 switch (method.getMEP()) { 630 case REQUEST_RESPONSE: 631 // input message 632 generateInputMessage(operation, method); 633 // output message 634 generateOutputMessage(operation, method); 635 break; 636 case ONE_WAY: 637 generateInputMessage(operation, method); 638 break; 639 default: 640 break; 641 } 642 // faults 643 for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { 644 QName messageName = new QName(model.getTargetNamespace(), exception.getMessageName()); 645 FaultType paramType = operation.fault().message(messageName).name(exception.getMessageName()); 646 extension.addOperationFaultExtension(paramType, method, exception); 647 } 648 } 649 } 650 651 /** 652 * Determines if the <CODE>method</CODE> is wrapper style 653 * @param method The {@link JavaMethod} to check if it is wrapper style 654 * @return true if the method is wrapper style, otherwise, false. 655 */ isWrapperStyle(JavaMethodImpl method)656 protected boolean isWrapperStyle(JavaMethodImpl method) { 657 if (method.getRequestParameters().size() > 0) { 658 ParameterImpl param = method.getRequestParameters().iterator().next(); 659 return param.isWrapperStyle(); 660 } 661 return false; 662 } 663 664 /** 665 * Determines if a {@link JavaMethod} is rpc/literal 666 * @param method The method to check 667 * @return true if method is rpc/literal, otherwise, false 668 */ isRpcLit(JavaMethodImpl method)669 protected boolean isRpcLit(JavaMethodImpl method) { 670 return method.getBinding().getStyle() == Style.RPC; 671 } 672 673 /** 674 * Generates the parameterOrder for a PortType operation 675 * @param operation The operation to generate the parameterOrder for 676 * @param method The {@link JavaMethod} to generate the parameterOrder from 677 */ generateParameterOrder(Operation operation, JavaMethodImpl method)678 protected void generateParameterOrder(Operation operation, JavaMethodImpl method) { 679 if (method.getMEP() == MEP.ONE_WAY) 680 return; 681 if (isRpcLit(method)) 682 generateRpcParameterOrder(operation, method); 683 else 684 generateDocumentParameterOrder(operation, method); 685 } 686 687 /** 688 * Generates the parameterOrder for a PortType operation 689 * @param operation the operation to generate the parameterOrder for 690 * @param method the {@link JavaMethod} to generate the parameterOrder from 691 */ generateRpcParameterOrder(Operation operation, JavaMethodImpl method)692 protected void generateRpcParameterOrder(Operation operation, JavaMethodImpl method) { 693 String partName; 694 StringBuilder paramOrder = new StringBuilder(); 695 Set<String> partNames = new HashSet<String>(); 696 List<ParameterImpl> sortedParams = sortMethodParameters(method); 697 int i = 0; 698 for (ParameterImpl parameter : sortedParams) { 699 if (parameter.getIndex() >= 0) { 700 partName = parameter.getPartName(); 701 if (!partNames.contains(partName)) { 702 if (i++ > 0) 703 paramOrder.append(' '); 704 paramOrder.append(partName); 705 partNames.add(partName); 706 } 707 } 708 } 709 if (i > 1) { 710 operation.parameterOrder(paramOrder.toString()); 711 } 712 } 713 714 715 /** 716 * Generates the parameterOrder for a PortType operation 717 * @param operation the operation to generate the parameterOrder for 718 * @param method the {@link JavaMethod} to generate the parameterOrder from 719 */ generateDocumentParameterOrder(Operation operation, JavaMethodImpl method)720 protected void generateDocumentParameterOrder(Operation operation, JavaMethodImpl method) { 721 String partName; 722 StringBuilder paramOrder = new StringBuilder(); 723 Set<String> partNames = new HashSet<String>(); 724 List<ParameterImpl> sortedParams = sortMethodParameters(method); 725 // boolean isWrapperStyle = isWrapperStyle(method); 726 int i = 0; 727 for (ParameterImpl parameter : sortedParams) { 728 // System.out.println("param: "+parameter.getIndex()+" name: "+parameter.getName().getLocalPart()); 729 if (parameter.getIndex() < 0) 730 continue; 731 732 // This should be safe change. if it affects compatibility, 733 // remove the following single statement and uncomment the code in block below. 734 partName = parameter.getPartName(); 735 /* 736 if (isWrapperStyle && isBodyParameter(parameter)) { 737 System.out.println("isWrapper and is body"); 738 if (method.getRequestParameters().contains(parameter)) 739 partName = PARAMETERS; 740 else { 741 //Rama: don't understand this logic "Response" below, 742 743 // really make sure this is a wrapper style wsdl we are creating 744 partName = RESPONSE; 745 } 746 } else { 747 partName = parameter.getPartName(); 748 }*/ 749 750 if (!partNames.contains(partName)) { 751 if (i++ > 0) 752 paramOrder.append(' '); 753 paramOrder.append(partName); 754 partNames.add(partName); 755 } 756 } 757 if (i > 1) { 758 operation.parameterOrder(paramOrder.toString()); 759 } 760 } 761 762 /** 763 * Sorts the parameters for the method by their position 764 * @param method the {@link JavaMethod} used to sort the parameters 765 * @return the sorted {@link List} of parameters 766 */ sortMethodParameters(JavaMethodImpl method)767 protected List<ParameterImpl> sortMethodParameters(JavaMethodImpl method) { 768 Set<ParameterImpl> paramSet = new HashSet<ParameterImpl>(); 769 List<ParameterImpl> sortedParams = new ArrayList<ParameterImpl>(); 770 if (isRpcLit(method)) { 771 for (ParameterImpl param : method.getRequestParameters()) { 772 if (param instanceof WrapperParameter) { 773 paramSet.addAll(((WrapperParameter) param).getWrapperChildren()); 774 } else { 775 paramSet.add(param); 776 } 777 } 778 for (ParameterImpl param : method.getResponseParameters()) { 779 if (param instanceof WrapperParameter) { 780 paramSet.addAll(((WrapperParameter) param).getWrapperChildren()); 781 } else { 782 paramSet.add(param); 783 } 784 } 785 } else { 786 paramSet.addAll(method.getRequestParameters()); 787 paramSet.addAll(method.getResponseParameters()); 788 } 789 Iterator<ParameterImpl> params = paramSet.iterator(); 790 if (paramSet.isEmpty()) 791 return sortedParams; 792 ParameterImpl param = params.next(); 793 sortedParams.add(param); 794 ParameterImpl sortedParam; 795 int pos; 796 for (int i = 1; i < paramSet.size(); i++) { 797 param = params.next(); 798 for (pos = 0; pos < i; pos++) { 799 sortedParam = sortedParams.get(pos); 800 if (param.getIndex() == sortedParam.getIndex() && 801 param instanceof WrapperParameter) 802 break; 803 if (param.getIndex() < sortedParam.getIndex()) { 804 break; 805 } 806 } 807 sortedParams.add(pos, param); 808 } 809 return sortedParams; 810 } 811 812 /** 813 * Determines if a parameter is associated with the message Body 814 * @param parameter the parameter to check 815 * @return true if the parameter is a <code>body</code> parameter 816 */ isBodyParameter(ParameterImpl parameter)817 protected boolean isBodyParameter(ParameterImpl parameter) { 818 ParameterBinding paramBinding = parameter.getBinding(); 819 return paramBinding.isBody(); 820 } 821 isHeaderParameter(ParameterImpl parameter)822 protected boolean isHeaderParameter(ParameterImpl parameter) { 823 ParameterBinding paramBinding = parameter.getBinding(); 824 return paramBinding.isHeader(); 825 } 826 isAttachmentParameter(ParameterImpl parameter)827 protected boolean isAttachmentParameter(ParameterImpl parameter) { 828 ParameterBinding paramBinding = parameter.getBinding(); 829 return paramBinding.isAttachment(); 830 } 831 832 833 /** 834 * Generates the Binding section of the WSDL 835 */ generateBinding()836 protected void generateBinding() { 837 Binding newBinding = serviceDefinitions.binding().name(model.getBoundPortTypeName().getLocalPart()); 838 extension.addBindingExtension(newBinding); 839 newBinding.type(model.getPortTypeName()); 840 boolean first = true; 841 for (JavaMethodImpl method : model.getJavaMethods()) { 842 if (first) { 843 SOAPBinding sBinding = method.getBinding(); 844 SOAPVersion soapVersion = sBinding.getSOAPVersion(); 845 if (soapVersion == SOAPVersion.SOAP_12) { 846 com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPBinding soapBinding = newBinding.soap12Binding(); 847 soapBinding.transport(this.binding.getBindingId().getTransport()); 848 if (sBinding.getStyle().equals(Style.DOCUMENT)) 849 soapBinding.style(DOCUMENT); 850 else 851 soapBinding.style(RPC); 852 } else { 853 com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPBinding soapBinding = newBinding.soapBinding(); 854 soapBinding.transport(this.binding.getBindingId().getTransport()); 855 if (sBinding.getStyle().equals(Style.DOCUMENT)) 856 soapBinding.style(DOCUMENT); 857 else 858 soapBinding.style(RPC); 859 } 860 first = false; 861 } 862 if (this.binding.getBindingId().getSOAPVersion() == SOAPVersion.SOAP_12) 863 generateSOAP12BindingOperation(method, newBinding); 864 else 865 generateBindingOperation(method, newBinding); 866 } 867 } 868 generateBindingOperation(JavaMethodImpl method, Binding binding)869 protected void generateBindingOperation(JavaMethodImpl method, Binding binding) { 870 BindingOperationType operation = binding.operation().name(method.getOperationName()); 871 extension.addBindingOperationExtension(operation, method); 872 String targetNamespace = model.getTargetNamespace(); 873 QName requestMessage = new QName(targetNamespace, method.getOperationName()); 874 List<ParameterImpl> bodyParams = new ArrayList<ParameterImpl>(); 875 List<ParameterImpl> headerParams = new ArrayList<ParameterImpl>(); 876 splitParameters(bodyParams, headerParams, method.getRequestParameters()); 877 SOAPBinding soapBinding = method.getBinding(); 878 operation.soapOperation().soapAction(soapBinding.getSOAPAction()); 879 880 // input 881 TypedXmlWriter input = operation.input(); 882 extension.addBindingOperationInputExtension(input, method); 883 BodyType body = input._element(Body.class); 884 boolean isRpc = soapBinding.getStyle().equals(Style.RPC); 885 if (soapBinding.getUse() == Use.LITERAL) { 886 body.use(LITERAL); 887 if (headerParams.size() > 0) { 888 if (bodyParams.size() > 0) { 889 ParameterImpl param = bodyParams.iterator().next(); 890 if (isRpc) { 891 StringBuilder parts = new StringBuilder(); 892 int i = 0; 893 for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { 894 if (i++ > 0) 895 parts.append(' '); 896 parts.append(parameter.getPartName()); 897 } 898 body.parts(parts.toString()); 899 } else { 900 body.parts(param.getPartName()); 901 } 902 } else { 903 body.parts(""); 904 } 905 generateSOAPHeaders(input, headerParams, requestMessage); 906 } 907 if (isRpc) { 908 body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); 909 } 910 } else { 911 // TODO localize this 912 throw new WebServiceException("encoded use is not supported"); 913 } 914 915 if (method.getMEP() != MEP.ONE_WAY) { 916 // output 917 bodyParams.clear(); 918 headerParams.clear(); 919 splitParameters(bodyParams, headerParams, method.getResponseParameters()); 920 TypedXmlWriter output = operation.output(); 921 extension.addBindingOperationOutputExtension(output, method); 922 body = output._element(Body.class); 923 body.use(LITERAL); 924 if (headerParams.size() > 0) { 925 StringBuilder parts = new StringBuilder(); 926 if (bodyParams.size() > 0) { 927 ParameterImpl param = bodyParams.iterator().hasNext() ? bodyParams.iterator().next() : null; 928 if (param != null) { 929 if (isRpc) { 930 int i = 0; 931 for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { 932 if (i++ > 0) { 933 parts.append(" "); 934 } 935 parts.append(parameter.getPartName()); 936 } 937 } else { 938 parts = new StringBuilder(param.getPartName()); 939 } 940 } 941 } 942 body.parts(parts.toString()); 943 QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); 944 generateSOAPHeaders(output, headerParams, responseMessage); 945 } 946 if (isRpc) { 947 body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); 948 } 949 } 950 for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { 951 Fault fault = operation.fault().name(exception.getMessageName()); 952 extension.addBindingOperationFaultExtension(fault, method, exception); 953 SOAPFault soapFault = fault._element(SOAPFault.class).name(exception.getMessageName()); 954 soapFault.use(LITERAL); 955 } 956 } 957 generateSOAP12BindingOperation(JavaMethodImpl method, Binding binding)958 protected void generateSOAP12BindingOperation(JavaMethodImpl method, Binding binding) { 959 BindingOperationType operation = binding.operation().name(method.getOperationName()); 960 extension.addBindingOperationExtension(operation, method); 961 String targetNamespace = model.getTargetNamespace(); 962 QName requestMessage = new QName(targetNamespace, method.getOperationName()); 963 ArrayList<ParameterImpl> bodyParams = new ArrayList<ParameterImpl>(); 964 ArrayList<ParameterImpl> headerParams = new ArrayList<ParameterImpl>(); 965 splitParameters(bodyParams, headerParams, method.getRequestParameters()); 966 SOAPBinding soapBinding = method.getBinding(); 967 968 String soapAction = soapBinding.getSOAPAction(); 969 if (soapAction != null) { 970 operation.soap12Operation().soapAction(soapAction); 971 } 972 973 // input 974 TypedXmlWriter input = operation.input(); 975 extension.addBindingOperationInputExtension(input, method); 976 com.sun.xml.internal.ws.wsdl.writer.document.soap12.BodyType body = input._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Body.class); 977 boolean isRpc = soapBinding.getStyle().equals(Style.RPC); 978 if (soapBinding.getUse().equals(Use.LITERAL)) { 979 body.use(LITERAL); 980 if (headerParams.size() > 0) { 981 if (bodyParams.size() > 0) { 982 ParameterImpl param = bodyParams.iterator().next(); 983 if (isRpc) { 984 StringBuilder parts = new StringBuilder(); 985 int i = 0; 986 for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { 987 if (i++ > 0) 988 parts.append(' '); 989 parts.append(parameter.getPartName()); 990 } 991 body.parts(parts.toString()); 992 } else { 993 body.parts(param.getPartName()); 994 } 995 } else { 996 body.parts(""); 997 } 998 generateSOAP12Headers(input, headerParams, requestMessage); 999 } 1000 if (isRpc) { 1001 body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); 1002 } 1003 } else { 1004 // TODO localize this 1005 throw new WebServiceException("encoded use is not supported"); 1006 } 1007 1008 if (method.getMEP() != MEP.ONE_WAY) { 1009 // output 1010 bodyParams.clear(); 1011 headerParams.clear(); 1012 splitParameters(bodyParams, headerParams, method.getResponseParameters()); 1013 TypedXmlWriter output = operation.output(); 1014 extension.addBindingOperationOutputExtension(output, method); 1015 body = output._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Body.class); 1016 body.use(LITERAL); 1017 if (headerParams.size() > 0) { 1018 if (bodyParams.size() > 0) { 1019 ParameterImpl param = bodyParams.iterator().next(); 1020 if (isRpc) { 1021 StringBuilder parts = new StringBuilder(); 1022 int i = 0; 1023 for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { 1024 if (i++ > 0) { 1025 parts.append(" "); 1026 } 1027 parts.append(parameter.getPartName()); 1028 } 1029 body.parts(parts.toString()); 1030 } else { 1031 body.parts(param.getPartName()); 1032 } 1033 } else { 1034 body.parts(""); 1035 } 1036 QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); 1037 generateSOAP12Headers(output, headerParams, responseMessage); 1038 } 1039 if (isRpc) { 1040 body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); 1041 } 1042 } 1043 for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { 1044 Fault fault = operation.fault().name(exception.getMessageName()); 1045 extension.addBindingOperationFaultExtension(fault, method, exception); 1046 com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPFault soapFault = fault._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPFault.class).name(exception.getMessageName()); 1047 soapFault.use(LITERAL); 1048 } 1049 } 1050 splitParameters(List<ParameterImpl> bodyParams, List<ParameterImpl> headerParams, List<ParameterImpl> params)1051 protected void splitParameters(List<ParameterImpl> bodyParams, List<ParameterImpl> headerParams, List<ParameterImpl> params) { 1052 for (ParameterImpl parameter : params) { 1053 if (isBodyParameter(parameter)) { 1054 bodyParams.add(parameter); 1055 } else { 1056 headerParams.add(parameter); 1057 } 1058 } 1059 } 1060 generateSOAPHeaders(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message)1061 protected void generateSOAPHeaders(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message) { 1062 1063 for (ParameterImpl headerParam : parameters) { 1064 Header header = writer._element(Header.class); 1065 header.message(message); 1066 header.part(headerParam.getPartName()); 1067 header.use(LITERAL); 1068 } 1069 } 1070 generateSOAP12Headers(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message)1071 protected void generateSOAP12Headers(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message) { 1072 1073 for (ParameterImpl headerParam : parameters) { 1074 com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header header = writer._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header.class); 1075 header.message(message); 1076 1077 1078 header.part(headerParam.getPartName()); 1079 header.use(LITERAL); 1080 } 1081 } 1082 1083 /** 1084 * Generates the Service section of the WSDL 1085 */ generateService()1086 protected void generateService() { 1087 QName portQName = model.getPortName(); 1088 QName serviceQName = model.getServiceQName(); 1089 Service service = serviceDefinitions.service().name(serviceQName.getLocalPart()); 1090 extension.addServiceExtension(service); 1091 Port port = service.port().name(portQName.getLocalPart()); 1092 port.binding(model.getBoundPortTypeName()); 1093 extension.addPortExtension(port); 1094 if (model.getJavaMethods().isEmpty()) 1095 return; 1096 1097 if (this.binding.getBindingId().getSOAPVersion() == SOAPVersion.SOAP_12) { 1098 com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress address = port._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress.class); 1099 address.location(endpointAddress); 1100 } else { 1101 SOAPAddress address = port._element(SOAPAddress.class); 1102 address.location(endpointAddress); 1103 } 1104 } 1105 generateInputMessage(Operation operation, JavaMethodImpl method)1106 protected void generateInputMessage(Operation operation, JavaMethodImpl method) { 1107 ParamType paramType = operation.input(); 1108 extension.addOperationInputExtension(paramType, method); 1109 // paramType.message(method.getOperation().getName()); 1110 paramType.message(new QName(model.getTargetNamespace(), method.getRequestMessageName())); 1111 } 1112 generateOutputMessage(Operation operation, JavaMethodImpl method)1113 protected void generateOutputMessage(Operation operation, JavaMethodImpl method) { 1114 ParamType paramType = operation.output(); 1115 extension.addOperationOutputExtension(paramType, method); 1116 // paramType.message(new QName(model.getTargetNamespace(), method.getOperation().getLocalName()+RESPONSE)); 1117 paramType.message(new QName(model.getTargetNamespace(), method.getResponseMessageName())); 1118 } 1119 1120 /** 1121 * Creates the {@link Result} object used by JAXB to generate a schema for the 1122 * namesapceUri namespace. 1123 * @param namespaceUri The namespace for the schema being generated 1124 * @param suggestedFileName the JAXB suggested file name for the schema file 1125 * @return the {@link Result} for JAXB to generate the schema into 1126 * @throws java.io.IOException thrown if on IO error occurs 1127 */ createOutputFile(String namespaceUri, String suggestedFileName)1128 public Result createOutputFile(String namespaceUri, String suggestedFileName) throws IOException { 1129 Result result; 1130 if (namespaceUri == null) { 1131 return null; 1132 } 1133 1134 Holder<String> fileNameHolder = new Holder<String>(); 1135 fileNameHolder.value = schemaPrefix + suggestedFileName; 1136 result = wsdlResolver.getSchemaOutput(namespaceUri, fileNameHolder); 1137 // System.out.println("schema file: "+fileNameHolder.value); 1138 // System.out.println("result: "+result); 1139 String schemaLoc; 1140 if (result == null) 1141 schemaLoc = fileNameHolder.value; 1142 else 1143 schemaLoc = relativize(result.getSystemId(), wsdlLocation); 1144 boolean isEmptyNs = namespaceUri.trim().equals(""); 1145 if (!isEmptyNs) { 1146 com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import(); 1147 _import.namespace(namespaceUri); 1148 _import.schemaLocation(schemaLoc); 1149 } 1150 return result; 1151 } 1152 createInlineSchema(String namespaceUri, String suggestedFileName)1153 private Result createInlineSchema(String namespaceUri, String suggestedFileName) throws IOException { 1154 Result result; 1155 if (namespaceUri.equals("")) { 1156 return null; 1157 } 1158 1159 // Holder<String> fileNameHolder = new Holder<String>(); 1160 // fileNameHolder.value = schemaPrefix+suggestedFileName; 1161 // result = wsdlResolver.getSchemaOutput(namespaceUri, fileNameHolder); 1162 // if (result == null) { 1163 // // JAXB doesn't have to generate it, a schema is already available 1164 // com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import().namespace(namespaceUri); 1165 // _import.schemaLocation(fileNameHolder.value); 1166 // } else { 1167 // Let JAXB write the schema directly into wsdl's TypedXmlWriter 1168 result = new TXWResult(types); 1169 result.setSystemId(""); 1170 // } 1171 return result; 1172 } 1173 1174 /** 1175 * Relativizes a URI by using another URI (base URI.) 1176 * 1177 * <p> 1178 * For example, {@code relative("http://www.sun.com/abc/def","http://www.sun.com/pqr/stu") => "../abc/def"} 1179 * 1180 * <p> 1181 * This method only works on hierarchical URI's, not opaque URI's (refer to the 1182 * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/URI.html">java.net.URI</a> 1183 * javadoc for complete definitions of these terms. 1184 * 1185 * <p> 1186 * This method will not normalize the relative URI. 1187 * @param uri the URI to relativize 1188 * 1189 * 1190 * @param baseUri the base URI to use for the relativization 1191 * @return the relative URI or the original URI if a relative one could not be computed 1192 */ relativize(String uri, String baseUri)1193 protected static String relativize(String uri, String baseUri) { 1194 try { 1195 assert uri != null; 1196 1197 if (baseUri == null) return uri; 1198 1199 URI theUri = new URI(escapeURI(uri)); 1200 URI theBaseUri = new URI(escapeURI(baseUri)); 1201 1202 if (theUri.isOpaque() || theBaseUri.isOpaque()) 1203 return uri; 1204 1205 if (!equalsIgnoreCase(theUri.getScheme(), theBaseUri.getScheme()) || 1206 !equal(theUri.getAuthority(), theBaseUri.getAuthority())) 1207 return uri; 1208 1209 String uriPath = theUri.getPath(); 1210 String basePath = theBaseUri.getPath(); 1211 1212 // normalize base path 1213 if (!basePath.endsWith("/")) { 1214 basePath = normalizeUriPath(basePath); 1215 } 1216 1217 if (uriPath.equals(basePath)) 1218 return "."; 1219 1220 String relPath = calculateRelativePath(uriPath, basePath); 1221 1222 if (relPath == null) 1223 return uri; // recursion found no commonality in the two uris at all 1224 StringBuilder relUri = new StringBuilder(); 1225 relUri.append(relPath); 1226 if (theUri.getQuery() != null) 1227 relUri.append('?').append(theUri.getQuery()); 1228 if (theUri.getFragment() != null) 1229 relUri.append('#').append(theUri.getFragment()); 1230 1231 return relUri.toString(); 1232 } catch (URISyntaxException e) { 1233 throw new InternalError("Error escaping one of these uris:\n\t" + uri + "\n\t" + baseUri); 1234 } 1235 } 1236 calculateRelativePath(String uri, String base)1237 private static String calculateRelativePath(String uri, String base) { 1238 if (base == null) { 1239 return null; 1240 } 1241 if (uri.startsWith(base)) { 1242 return uri.substring(base.length()); 1243 } else { 1244 return "../" + calculateRelativePath(uri, getParentUriPath(base)); 1245 } 1246 } 1247 1248 1249 /** 1250 * Implements the SchemaOutputResolver used by JAXB to 1251 */ 1252 protected class JAXWSOutputSchemaResolver extends SchemaOutputResolver { 1253 ArrayList<DOMResult> nonGlassfishSchemas = null; 1254 1255 /** 1256 * Creates the {@link Result} object used by JAXB to generate a schema for the 1257 * namesapceUri namespace. 1258 * @param namespaceUri The namespace for the schema being generated 1259 * @param suggestedFileName the JAXB suggested file name for the schema file 1260 * @return the {@link Result} for JAXB to generate the schema into 1261 * @throws java.io.IOException thrown if on IO error occurs 1262 */ 1263 @Override createOutput(String namespaceUri, String suggestedFileName)1264 public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { 1265 return inlineSchemas 1266 ? ((nonGlassfishSchemas != null) ? nonGlassfishSchemaResult(namespaceUri, suggestedFileName) : createInlineSchema(namespaceUri, suggestedFileName)) 1267 // ? createInlineSchema(namespaceUri, suggestedFileName) 1268 : createOutputFile(namespaceUri, suggestedFileName); 1269 } 1270 nonGlassfishSchemaResult(String namespaceUri, String suggestedFileName)1271 private Result nonGlassfishSchemaResult(String namespaceUri, String suggestedFileName) throws IOException { 1272 DOMResult result = new DOMResult(); 1273 result.setSystemId(""); 1274 nonGlassfishSchemas.add(result); 1275 return result; 1276 } 1277 } 1278 register(WSDLGeneratorExtension h)1279 private void register(WSDLGeneratorExtension h) { 1280 extensionHandlers.add(h); 1281 } 1282 } 1283