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