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 */ 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 */ 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 */ 276 public void setEndpointAddress(String address) { 277 this.endpointAddress = address; 278 } 279 280 protected String mangleName(String name) { 281 return BindingHelper.mangleNameToClassName(name); 282 } 283 284 /** 285 * Performes the actual WSDL generation 286 */ 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 334 CommentFilter(XmlSerializer serializer) { 335 this.serializer = serializer; 336 } 337 338 @Override 339 public void startDocument() { 340 serializer.startDocument(); 341 comment(new StringBuilder(VERSION_COMMENT)); 342 text(new StringBuilder("\n")); 343 } 344 345 @Override 346 public void beginStartTag(String uri, String localName, String prefix) { 347 serializer.beginStartTag(uri, localName, prefix); 348 } 349 350 @Override 351 public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) { 352 serializer.writeAttribute(uri, localName, prefix, value); 353 } 354 355 @Override 356 public void writeXmlns(String prefix, String uri) { 357 serializer.writeXmlns(prefix, uri); 358 } 359 360 @Override 361 public void endStartTag(String uri, String localName, String prefix) { 362 serializer.endStartTag(uri, localName, prefix); 363 } 364 365 @Override 366 public void endTag() { 367 serializer.endTag(); 368 } 369 370 @Override 371 public void text(StringBuilder text) { 372 serializer.text(text); 373 } 374 375 @Override 376 public void cdata(StringBuilder text) { 377 serializer.cdata(text); 378 } 379 380 @Override 381 public void comment(StringBuilder comment) { 382 serializer.comment(comment); 383 } 384 385 @Override 386 public void endDocument() { 387 serializer.endDocument(); 388 } 389 390 @Override 391 public void flush() { 392 serializer.flush(); 393 } 394 395 } 396 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 817 protected boolean isBodyParameter(ParameterImpl parameter) { 818 ParameterBinding paramBinding = parameter.getBinding(); 819 return paramBinding.isBody(); 820 } 821 822 protected boolean isHeaderParameter(ParameterImpl parameter) { 823 ParameterBinding paramBinding = parameter.getBinding(); 824 return paramBinding.isHeader(); 825 } 826 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 */ 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 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 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 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 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 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 */ 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 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 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 */ 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 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 */ 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 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 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 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 1279 private void register(WSDLGeneratorExtension h) { 1280 extensionHandlers.add(h); 1281 } 1282 }