Thu, 31 Aug 2017 15:18:52 +0800
merge
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 */
26 package com.sun.xml.internal.ws.wsdl.writer;
29 import static com.sun.xml.internal.bind.v2.schemagen.Util.*;
31 import com.oracle.webservices.internal.api.databinding.WSDLResolver;
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;
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;
102 import org.w3c.dom.Document;
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;
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;
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";
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;
207 private String endpointAddress = REPLACE_WITH_ACTUAL_URL;
208 private Container container;
209 private final Class implType;
211 private boolean inlineSchemas; // TODO
212 private final boolean disableXmlSecurity;
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 }
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) {
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;
250 // register handlers for default extensions
251 register(new W3CAddressingWSDLGeneratorExtension());
252 register(new W3CAddressingMetadataWSDLGeneratorExtension());
253 register(new PolicyWSDLGeneratorExtension());
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 }
264 for (WSDLGeneratorExtension w : extensions)
265 register(w);
267 this.extension = new WSDLGeneratorExtensionFacade(extensionHandlers.toArray(new WSDLGeneratorExtension[0]));
268 }
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 }
280 protected String mangleName(String name) {
281 return BindingHelper.mangleNameToClassName(name);
282 }
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);
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 }
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 + ". ";
334 CommentFilter(XmlSerializer serializer) {
335 this.serializer = serializer;
336 }
338 @Override
339 public void startDocument() {
340 serializer.startDocument();
341 comment(new StringBuilder(VERSION_COMMENT));
342 text(new StringBuilder("\n"));
343 }
345 @Override
346 public void beginStartTag(String uri, String localName, String prefix) {
347 serializer.beginStartTag(uri, localName, prefix);
348 }
350 @Override
351 public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
352 serializer.writeAttribute(uri, localName, prefix, value);
353 }
355 @Override
356 public void writeXmlns(String prefix, String uri) {
357 serializer.writeXmlns(prefix, uri);
358 }
360 @Override
361 public void endStartTag(String uri, String localName, String prefix) {
362 serializer.endStartTag(uri, localName, prefix);
363 }
365 @Override
366 public void endTag() {
367 serializer.endTag();
368 }
370 @Override
371 public void text(StringBuilder text) {
372 serializer.text(text);
373 }
375 @Override
376 public void cdata(StringBuilder text) {
377 serializer.cdata(text);
378 }
380 @Override
381 public void comment(StringBuilder comment) {
382 serializer.comment(comment);
383 }
385 @Override
386 public void endDocument() {
387 serializer.endDocument();
388 }
390 @Override
391 public void flush() {
392 serializer.flush();
393 }
395 }
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 }
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);
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 }
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 }
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 }
540 /**
541 * Generates the WSDL messages
542 */
543 protected void generateMessages() {
544 for (JavaMethodImpl method : model.getJavaMethods()) {
545 generateSOAPMessages(method, method.getBinding());
546 }
547 }
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;
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);
585 for (ParameterImpl param : method.getResponseParameters()) {
586 if (isDoclit) {
587 part = message.part().name(param.getPartName());
588 part.element(param.getName());
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);
611 extension.addFaultMessageExtension(message, method, exception);
612 part = message.part().name("fault");//tagName.getLocalPart());
613 part.element(tagName);
614 processedExceptions.add(messageQName);
615 }
616 }
618 /**
619 * Generates the WSDL portType
620 */
621 protected void generatePortType() {
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 }
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 }
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 }
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 }
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 }
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;
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,
743 // really make sure this is a wrapper style wsdl we are creating
744 partName = RESPONSE;
745 }
746 } else {
747 partName = parameter.getPartName();
748 }*/
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 }
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 }
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 }
822 protected boolean isHeaderParameter(ParameterImpl parameter) {
823 ParameterBinding paramBinding = parameter.getBinding();
824 return paramBinding.isHeader();
825 }
827 protected boolean isAttachmentParameter(ParameterImpl parameter) {
828 ParameterBinding paramBinding = parameter.getBinding();
829 return paramBinding.isAttachment();
830 }
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 }
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());
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 }
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 }
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();
968 String soapAction = soapBinding.getSOAPAction();
969 if (soapAction != null) {
970 operation.soap12Operation().soapAction(soapAction);
971 }
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 }
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 }
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 }
1061 protected void generateSOAPHeaders(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message) {
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 }
1071 protected void generateSOAP12Headers(TypedXmlWriter writer, List<ParameterImpl> parameters, QName message) {
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);
1078 header.part(headerParam.getPartName());
1079 header.use(LITERAL);
1080 }
1081 }
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;
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 }
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 }
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 }
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 }
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 }
1153 private Result createInlineSchema(String namespaceUri, String suggestedFileName) throws IOException {
1154 Result result;
1155 if (namespaceUri.equals("")) {
1156 return null;
1157 }
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 }
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;
1197 if (baseUri == null) return uri;
1199 URI theUri = new URI(escapeURI(uri));
1200 URI theBaseUri = new URI(escapeURI(baseUri));
1202 if (theUri.isOpaque() || theBaseUri.isOpaque())
1203 return uri;
1205 if (!equalsIgnoreCase(theUri.getScheme(), theBaseUri.getScheme()) ||
1206 !equal(theUri.getAuthority(), theBaseUri.getAuthority()))
1207 return uri;
1209 String uriPath = theUri.getPath();
1210 String basePath = theBaseUri.getPath();
1212 // normalize base path
1213 if (!basePath.endsWith("/")) {
1214 basePath = normalizeUriPath(basePath);
1215 }
1217 if (uriPath.equals(basePath))
1218 return ".";
1220 String relPath = calculateRelativePath(uriPath, basePath);
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());
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 }
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 }
1249 /**
1250 * Implements the SchemaOutputResolver used by JAXB to
1251 */
1252 protected class JAXWSOutputSchemaResolver extends SchemaOutputResolver {
1253 ArrayList<DOMResult> nonGlassfishSchemas = null;
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 }
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 }
1279 private void register(WSDLGeneratorExtension h) {
1280 extensionHandlers.add(h);
1281 }
1282 }