aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.wsdl.writer; aoqi@0: aoqi@0: aoqi@0: import static com.sun.xml.internal.bind.v2.schemagen.Util.*; aoqi@0: aoqi@0: import com.oracle.webservices.internal.api.databinding.WSDLResolver; aoqi@0: aoqi@0: import com.sun.xml.internal.txw2.TXW; aoqi@0: import com.sun.xml.internal.txw2.TypedXmlWriter; aoqi@0: import com.sun.xml.internal.txw2.output.ResultFactory; aoqi@0: import com.sun.xml.internal.txw2.output.XmlSerializer; aoqi@0: import com.sun.xml.internal.txw2.output.TXWResult; aoqi@0: import com.sun.xml.internal.ws.api.SOAPVersion; aoqi@0: import com.sun.xml.internal.ws.api.WSBinding; aoqi@0: import com.sun.xml.internal.ws.api.model.JavaMethod; aoqi@0: import com.sun.xml.internal.ws.api.model.MEP; aoqi@0: import com.sun.xml.internal.ws.api.model.ParameterBinding; aoqi@0: import com.sun.xml.internal.ws.api.model.SEIModel; aoqi@0: import com.sun.xml.internal.ws.api.model.soap.SOAPBinding; aoqi@0: import com.sun.xml.internal.ws.api.server.Container; aoqi@0: import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension; aoqi@0: import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGenExtnContext; aoqi@0: import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; aoqi@0: import com.sun.xml.internal.ws.model.CheckedExceptionImpl; aoqi@0: import com.sun.xml.internal.ws.model.JavaMethodImpl; aoqi@0: import com.sun.xml.internal.ws.model.ParameterImpl; aoqi@0: import com.sun.xml.internal.ws.model.WrapperParameter; aoqi@0: import com.sun.xml.internal.ws.util.xml.XmlUtil; aoqi@0: import com.sun.xml.internal.ws.wsdl.parser.SOAPConstants; aoqi@0: import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Binding; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.BindingOperationType; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Definitions; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Fault; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.FaultType; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Import; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Message; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Operation; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.ParamType; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Port; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.PortType; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Service; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.Types; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.soap.Body; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.soap.BodyType; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.soap.Header; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPAddress; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPFault; aoqi@0: import com.sun.xml.internal.ws.wsdl.writer.document.xsd.Schema; aoqi@0: import com.sun.xml.internal.ws.spi.db.BindingContext; aoqi@0: import com.sun.xml.internal.ws.spi.db.BindingHelper; aoqi@0: import com.sun.xml.internal.ws.spi.db.TypeInfo; aoqi@0: import com.sun.xml.internal.ws.spi.db.WrapperComposite; aoqi@0: import com.sun.xml.internal.ws.util.RuntimeVersion; aoqi@0: import com.sun.xml.internal.ws.policy.jaxws.PolicyWSDLGeneratorExtension; aoqi@0: import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants; aoqi@0: import com.sun.xml.internal.bind.v2.schemagen.xmlschema.Element; aoqi@0: import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ComplexType; aoqi@0: import com.sun.xml.internal.bind.v2.schemagen.xmlschema.ExplicitGroup; aoqi@0: import com.sun.xml.internal.bind.v2.schemagen.xmlschema.LocalElement; aoqi@0: aoqi@0: import javax.jws.soap.SOAPBinding.Style; aoqi@0: import javax.jws.soap.SOAPBinding.Use; aoqi@0: import javax.xml.bind.SchemaOutputResolver; aoqi@0: import javax.xml.namespace.QName; aoqi@0: import javax.xml.transform.Result; aoqi@0: import javax.xml.transform.Transformer; aoqi@0: import javax.xml.transform.TransformerConfigurationException; aoqi@0: import javax.xml.transform.TransformerException; aoqi@0: import javax.xml.transform.TransformerFactory; aoqi@0: import javax.xml.transform.dom.DOMResult; aoqi@0: import javax.xml.transform.dom.DOMSource; aoqi@0: import javax.xml.transform.sax.SAXResult; aoqi@0: import javax.xml.ws.Holder; aoqi@0: import javax.xml.ws.WebServiceException; aoqi@0: aoqi@0: import org.w3c.dom.Document; aoqi@0: aoqi@0: import java.io.IOException; aoqi@0: import java.net.URI; aoqi@0: import java.net.URISyntaxException; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.HashSet; aoqi@0: import java.util.Iterator; aoqi@0: import java.util.List; aoqi@0: import java.util.Set; aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Class used to generate WSDLs from a {@link SEIModel}. aoqi@0: * aoqi@0: * @author WS Development Team aoqi@0: */ aoqi@0: public class WSDLGenerator { aoqi@0: private JAXWSOutputSchemaResolver resolver; aoqi@0: private WSDLResolver wsdlResolver = null; aoqi@0: private AbstractSEIModelImpl model; aoqi@0: private Definitions serviceDefinitions; aoqi@0: private Definitions portDefinitions; aoqi@0: private Types types; aoqi@0: /** aoqi@0: * Constant String for ".wsdl" aoqi@0: */ aoqi@0: private static final String DOT_WSDL = ".wsdl"; aoqi@0: /** aoqi@0: * Constant String appended to response message names aoqi@0: */ aoqi@0: private static final String RESPONSE = "Response"; aoqi@0: /** aoqi@0: * constant String used for part name for wrapped request messages aoqi@0: */ aoqi@0: private static final String PARAMETERS = "parameters"; aoqi@0: /** aoqi@0: * the part name for unwrappable response messages aoqi@0: */ aoqi@0: private static final String RESULT = "parameters"; aoqi@0: /** aoqi@0: * the part name for response messages that are not unwrappable aoqi@0: */ aoqi@0: private static final String UNWRAPPABLE_RESULT = "result"; aoqi@0: /** aoqi@0: * The WSDL namespace aoqi@0: */ aoqi@0: private static final String WSDL_NAMESPACE = WSDLConstants.NS_WSDL; aoqi@0: aoqi@0: /** aoqi@0: * the XSD namespace aoqi@0: */ aoqi@0: private static final String XSD_NAMESPACE = SOAPNamespaceConstants.XSD; aoqi@0: /** aoqi@0: * the namespace prefix to use for the XSD namespace aoqi@0: */ aoqi@0: private static final String XSD_PREFIX = "xsd"; aoqi@0: /** aoqi@0: * The SOAP 1.1 namespace aoqi@0: */ aoqi@0: private static final String SOAP11_NAMESPACE = SOAPConstants.NS_WSDL_SOAP; aoqi@0: /** aoqi@0: * The SOAP 1.2 namespace aoqi@0: */ aoqi@0: private static final String SOAP12_NAMESPACE = SOAPConstants.NS_WSDL_SOAP12; aoqi@0: /** aoqi@0: * The namespace prefix to use for the SOAP 1.1 namespace aoqi@0: */ aoqi@0: private static final String SOAP_PREFIX = "soap"; aoqi@0: /** aoqi@0: * The namespace prefix to use for the SOAP 1.2 namespace aoqi@0: */ aoqi@0: private static final String SOAP12_PREFIX = "soap12"; aoqi@0: /** aoqi@0: * The namespace prefix to use for the targetNamespace aoqi@0: */ aoqi@0: private static final String TNS_PREFIX = "tns"; aoqi@0: aoqi@0: /** aoqi@0: * Constant String "document" used to specify document style aoqi@0: * soapBindings aoqi@0: */ aoqi@0: private static final String DOCUMENT = "document"; aoqi@0: /** aoqi@0: * Constant String "rpc" used to specify rpc style aoqi@0: * soapBindings aoqi@0: */ aoqi@0: private static final String RPC = "rpc"; aoqi@0: /** aoqi@0: * Constant String "literal" used to create literal use binddings aoqi@0: */ aoqi@0: private static final String LITERAL = "literal"; aoqi@0: /** aoqi@0: * Constant String to flag the URL to replace at runtime for the endpoint aoqi@0: */ aoqi@0: private static final String REPLACE_WITH_ACTUAL_URL = "REPLACE_WITH_ACTUAL_URL"; aoqi@0: private Set processedExceptions = new HashSet(); aoqi@0: private WSBinding binding; aoqi@0: private String wsdlLocation; aoqi@0: private String portWSDLID; aoqi@0: private String schemaPrefix; aoqi@0: private WSDLGeneratorExtension extension; aoqi@0: List extensionHandlers; aoqi@0: aoqi@0: private String endpointAddress = REPLACE_WITH_ACTUAL_URL; aoqi@0: private Container container; aoqi@0: private final Class implType; aoqi@0: aoqi@0: private boolean inlineSchemas; // TODO aoqi@0: private final boolean disableXmlSecurity; aoqi@0: aoqi@0: /** aoqi@0: * Creates the WSDLGenerator aoqi@0: * @param model The {@link AbstractSEIModelImpl} used to generate the WSDL aoqi@0: * @param wsdlResolver The {@link WSDLResolver} to use resovle names while generating the WSDL aoqi@0: * @param binding specifies which {@link javax.xml.ws.BindingType} to generate aoqi@0: * @param extensions an array {@link WSDLGeneratorExtension} that will aoqi@0: * be invoked to generate WSDL extensions aoqi@0: */ aoqi@0: public WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, aoqi@0: Class implType, boolean inlineSchemas, WSDLGeneratorExtension... extensions) { aoqi@0: this(model, wsdlResolver, binding, container, implType, inlineSchemas, false, extensions); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Creates the WSDLGenerator aoqi@0: * @param model The {@link AbstractSEIModelImpl} used to generate the WSDL aoqi@0: * @param wsdlResolver The {@link WSDLResolver} to use resovle names while generating the WSDL aoqi@0: * @param binding specifies which {@link javax.xml.ws.BindingType} to generate aoqi@0: * @param disableXmlSecurity specifies whether to disable the secure xml processing feature aoqi@0: * @param extensions an array {@link WSDLGeneratorExtension} that will aoqi@0: * be invoked to generate WSDL extensions aoqi@0: */ aoqi@0: public WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, aoqi@0: Class implType, boolean inlineSchemas, boolean disableXmlSecurity, aoqi@0: WSDLGeneratorExtension... extensions) { aoqi@0: aoqi@0: this.model = model; aoqi@0: resolver = new JAXWSOutputSchemaResolver(); aoqi@0: this.wsdlResolver = wsdlResolver; aoqi@0: this.binding = binding; aoqi@0: this.container = container; aoqi@0: this.implType = implType; aoqi@0: extensionHandlers = new ArrayList(); aoqi@0: this.inlineSchemas = inlineSchemas; aoqi@0: this.disableXmlSecurity = disableXmlSecurity; aoqi@0: aoqi@0: // register handlers for default extensions aoqi@0: register(new W3CAddressingWSDLGeneratorExtension()); aoqi@0: register(new W3CAddressingMetadataWSDLGeneratorExtension()); aoqi@0: register(new PolicyWSDLGeneratorExtension()); aoqi@0: aoqi@0: if (container != null) { // on server aoqi@0: WSDLGeneratorExtension[] wsdlGeneratorExtensions = container.getSPI(WSDLGeneratorExtension[].class); aoqi@0: if (wsdlGeneratorExtensions != null) { aoqi@0: for (WSDLGeneratorExtension wsdlGeneratorExtension : wsdlGeneratorExtensions) { aoqi@0: register(wsdlGeneratorExtension); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: for (WSDLGeneratorExtension w : extensions) aoqi@0: register(w); aoqi@0: aoqi@0: this.extension = new WSDLGeneratorExtensionFacade(extensionHandlers.toArray(new WSDLGeneratorExtension[0])); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Sets the endpoint address string to be written. aoqi@0: * Defaults to {@link #REPLACE_WITH_ACTUAL_URL}. aoqi@0: * aoqi@0: * @param address wsdl:port/soap:address/[@location] value aoqi@0: */ aoqi@0: public void setEndpointAddress(String address) { aoqi@0: this.endpointAddress = address; aoqi@0: } aoqi@0: aoqi@0: protected String mangleName(String name) { aoqi@0: return BindingHelper.mangleNameToClassName(name); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Performes the actual WSDL generation aoqi@0: */ aoqi@0: public void doGeneration() { aoqi@0: XmlSerializer serviceWriter; aoqi@0: XmlSerializer portWriter = null; aoqi@0: String fileName = mangleName(model.getServiceQName().getLocalPart()); aoqi@0: Result result = wsdlResolver.getWSDL(fileName + DOT_WSDL); aoqi@0: wsdlLocation = result.getSystemId(); aoqi@0: serviceWriter = new CommentFilter(ResultFactory.createSerializer(result)); aoqi@0: if (model.getServiceQName().getNamespaceURI().equals(model.getTargetNamespace())) { aoqi@0: portWriter = serviceWriter; aoqi@0: schemaPrefix = fileName + "_"; aoqi@0: } else { aoqi@0: String wsdlName = mangleName(model.getPortTypeName().getLocalPart()); aoqi@0: if (wsdlName.equals(fileName)) aoqi@0: wsdlName += "PortType"; aoqi@0: Holder absWSDLName = new Holder(); aoqi@0: absWSDLName.value = wsdlName + DOT_WSDL; aoqi@0: result = wsdlResolver.getAbstractWSDL(absWSDLName); aoqi@0: aoqi@0: if (result != null) { aoqi@0: portWSDLID = result.getSystemId(); aoqi@0: if (portWSDLID.equals(wsdlLocation)) { aoqi@0: portWriter = serviceWriter; aoqi@0: } else { aoqi@0: portWriter = new CommentFilter(ResultFactory.createSerializer(result)); aoqi@0: } aoqi@0: } else { aoqi@0: portWSDLID = absWSDLName.value; aoqi@0: } aoqi@0: schemaPrefix = new java.io.File(portWSDLID).getName(); aoqi@0: int idx = schemaPrefix.lastIndexOf('.'); aoqi@0: if (idx > 0) aoqi@0: schemaPrefix = schemaPrefix.substring(0, idx); aoqi@0: schemaPrefix = mangleName(schemaPrefix) + "_"; aoqi@0: } aoqi@0: generateDocument(serviceWriter, portWriter); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Writing directly to XmlSerializer is a problem, since it doesn't suppress aoqi@0: * xml declaration. Creating filter so that comment is written before TXW writes aoqi@0: * anything in the WSDL. aoqi@0: */ aoqi@0: private static class CommentFilter implements XmlSerializer { aoqi@0: final XmlSerializer serializer; aoqi@0: private static final String VERSION_COMMENT = aoqi@0: " Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is " + RuntimeVersion.VERSION + ". "; aoqi@0: aoqi@0: CommentFilter(XmlSerializer serializer) { aoqi@0: this.serializer = serializer; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void startDocument() { aoqi@0: serializer.startDocument(); aoqi@0: comment(new StringBuilder(VERSION_COMMENT)); aoqi@0: text(new StringBuilder("\n")); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void beginStartTag(String uri, String localName, String prefix) { aoqi@0: serializer.beginStartTag(uri, localName, prefix); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) { aoqi@0: serializer.writeAttribute(uri, localName, prefix, value); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void writeXmlns(String prefix, String uri) { aoqi@0: serializer.writeXmlns(prefix, uri); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void endStartTag(String uri, String localName, String prefix) { aoqi@0: serializer.endStartTag(uri, localName, prefix); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void endTag() { aoqi@0: serializer.endTag(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void text(StringBuilder text) { aoqi@0: serializer.text(text); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void cdata(StringBuilder text) { aoqi@0: serializer.cdata(text); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void comment(StringBuilder comment) { aoqi@0: serializer.comment(comment); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void endDocument() { aoqi@0: serializer.endDocument(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void flush() { aoqi@0: serializer.flush(); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: private void generateDocument(XmlSerializer serviceStream, XmlSerializer portStream) { aoqi@0: serviceDefinitions = TXW.create(Definitions.class, serviceStream); aoqi@0: serviceDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); aoqi@0: serviceDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); aoqi@0: serviceDefinitions.targetNamespace(model.getServiceQName().getNamespaceURI()); aoqi@0: serviceDefinitions._namespace(model.getServiceQName().getNamespaceURI(), TNS_PREFIX); aoqi@0: if (binding.getSOAPVersion() == SOAPVersion.SOAP_12) aoqi@0: serviceDefinitions._namespace(SOAP12_NAMESPACE, SOAP12_PREFIX); aoqi@0: else aoqi@0: serviceDefinitions._namespace(SOAP11_NAMESPACE, SOAP_PREFIX); aoqi@0: serviceDefinitions.name(model.getServiceQName().getLocalPart()); aoqi@0: WSDLGenExtnContext serviceCtx = new WSDLGenExtnContext(serviceDefinitions, model, binding, container, implType); aoqi@0: extension.start(serviceCtx); aoqi@0: if (serviceStream != portStream && portStream != null) { aoqi@0: // generate an abstract and concrete wsdl aoqi@0: portDefinitions = TXW.create(Definitions.class, portStream); aoqi@0: portDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); aoqi@0: portDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); aoqi@0: if (model.getTargetNamespace() != null) { aoqi@0: portDefinitions.targetNamespace(model.getTargetNamespace()); aoqi@0: portDefinitions._namespace(model.getTargetNamespace(), TNS_PREFIX); aoqi@0: } aoqi@0: aoqi@0: String schemaLoc = relativize(portWSDLID, wsdlLocation); aoqi@0: Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); aoqi@0: _import.location(schemaLoc); aoqi@0: } else if (portStream != null) { aoqi@0: // abstract and concrete are the same aoqi@0: portDefinitions = serviceDefinitions; aoqi@0: } else { aoqi@0: // import a provided abstract wsdl aoqi@0: String schemaLoc = relativize(portWSDLID, wsdlLocation); aoqi@0: Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); aoqi@0: _import.location(schemaLoc); aoqi@0: } aoqi@0: extension.addDefinitionsExtension(serviceDefinitions); aoqi@0: aoqi@0: if (portDefinitions != null) { aoqi@0: generateTypes(); aoqi@0: generateMessages(); aoqi@0: generatePortType(); aoqi@0: } aoqi@0: generateBinding(); aoqi@0: generateService(); aoqi@0: //Give a chance to WSDLGeneratorExtensions to write stuff before closing aoqi@0: extension.end(serviceCtx); aoqi@0: serviceDefinitions.commit(); aoqi@0: if (portDefinitions != null && portDefinitions != serviceDefinitions) aoqi@0: portDefinitions.commit(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Generates the types section of the WSDL aoqi@0: */ aoqi@0: protected void generateTypes() { aoqi@0: types = portDefinitions.types(); aoqi@0: if (model.getBindingContext() != null) { aoqi@0: if (inlineSchemas && model.getBindingContext().getClass().getName().indexOf("glassfish") == -1) { aoqi@0: resolver.nonGlassfishSchemas = new ArrayList(); aoqi@0: } aoqi@0: try { aoqi@0: model.getBindingContext().generateSchema(resolver); aoqi@0: } catch (IOException e) { aoqi@0: // TODO locallize and wrap this aoqi@0: throw new WebServiceException(e.getMessage()); aoqi@0: } aoqi@0: } aoqi@0: if (resolver.nonGlassfishSchemas != null) { aoqi@0: TransformerFactory tf = XmlUtil.newTransformerFactory(!disableXmlSecurity); aoqi@0: try { aoqi@0: Transformer t = tf.newTransformer(); aoqi@0: for (DOMResult xsd : resolver.nonGlassfishSchemas) { aoqi@0: Document doc = (Document) xsd.getNode(); aoqi@0: SAXResult sax = new SAXResult(new TXWContentHandler(types)); aoqi@0: t.transform(new DOMSource(doc.getDocumentElement()), sax); aoqi@0: } aoqi@0: } catch (TransformerConfigurationException e) { aoqi@0: throw new WebServiceException(e.getMessage(), e); aoqi@0: } catch (TransformerException e) { aoqi@0: throw new WebServiceException(e.getMessage(), e); aoqi@0: } aoqi@0: } aoqi@0: generateWrappers(); aoqi@0: } aoqi@0: aoqi@0: void generateWrappers() { aoqi@0: List wrappers = new ArrayList(); aoqi@0: for (JavaMethodImpl method : model.getJavaMethods()) { aoqi@0: if(method.getBinding().isRpcLit()) continue; aoqi@0: for (ParameterImpl p : method.getRequestParameters()) { aoqi@0: if (p instanceof WrapperParameter) { aoqi@0: if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { aoqi@0: wrappers.add((WrapperParameter)p); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: for (ParameterImpl p : method.getResponseParameters()) { aoqi@0: if (p instanceof WrapperParameter) { aoqi@0: if (WrapperComposite.class.equals((((WrapperParameter)p).getTypeInfo().type))) { aoqi@0: wrappers.add((WrapperParameter)p); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: if (wrappers.isEmpty()) return; aoqi@0: HashMap xsds = new HashMap(); aoqi@0: for(WrapperParameter wp : wrappers) { aoqi@0: String tns = wp.getName().getNamespaceURI(); aoqi@0: Schema xsd = xsds.get(tns); aoqi@0: if (xsd == null) { aoqi@0: xsd = types.schema(); aoqi@0: xsd.targetNamespace(tns); aoqi@0: xsds.put(tns, xsd); aoqi@0: } aoqi@0: Element e = xsd._element(Element.class); aoqi@0: e._attribute("name", wp.getName().getLocalPart()); aoqi@0: e.type(wp.getName()); aoqi@0: ComplexType ct = xsd._element(ComplexType.class); aoqi@0: ct._attribute("name", wp.getName().getLocalPart()); aoqi@0: ExplicitGroup sq = ct.sequence(); aoqi@0: for (ParameterImpl p : wp.getWrapperChildren() ) { aoqi@0: if (p.getBinding().isBody()) { aoqi@0: LocalElement le = sq.element(); aoqi@0: le._attribute("name", p.getName().getLocalPart()); aoqi@0: TypeInfo typeInfo = p.getItemType(); aoqi@0: boolean repeatedElement = false; aoqi@0: if (typeInfo == null) { aoqi@0: typeInfo = p.getTypeInfo(); aoqi@0: } else { aoqi@0: repeatedElement = true; aoqi@0: } aoqi@0: QName type = model.getBindingContext().getTypeName(typeInfo); aoqi@0: le.type(type); aoqi@0: if (repeatedElement) { aoqi@0: le.minOccurs(0); aoqi@0: le.maxOccurs("unbounded"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates the WSDL messages aoqi@0: */ aoqi@0: protected void generateMessages() { aoqi@0: for (JavaMethodImpl method : model.getJavaMethods()) { aoqi@0: generateSOAPMessages(method, method.getBinding()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates messages for a SOAPBinding aoqi@0: * @param method The {@link JavaMethod} to generate messages for aoqi@0: * @param binding The {@link com.sun.xml.internal.ws.api.model.soap.SOAPBinding} to add the generated messages to aoqi@0: */ aoqi@0: protected void generateSOAPMessages(JavaMethodImpl method, com.sun.xml.internal.ws.api.model.soap.SOAPBinding binding) { aoqi@0: boolean isDoclit = binding.isDocLit(); aoqi@0: // Message message = portDefinitions.message().name(method.getOperation().getName().getLocalPart()); aoqi@0: Message message = portDefinitions.message().name(method.getRequestMessageName()); aoqi@0: extension.addInputMessageExtension(message, method); aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.Part part; aoqi@0: BindingContext jaxbContext = model.getBindingContext(); aoqi@0: boolean unwrappable = true; aoqi@0: for (ParameterImpl param : method.getRequestParameters()) { aoqi@0: if (isDoclit) { aoqi@0: if (isHeaderParameter(param)) aoqi@0: unwrappable = false; aoqi@0: aoqi@0: part = message.part().name(param.getPartName()); aoqi@0: part.element(param.getName()); aoqi@0: } else { aoqi@0: if (param.isWrapperStyle()) { aoqi@0: for (ParameterImpl childParam : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: part = message.part().name(childParam.getPartName()); aoqi@0: part.type(jaxbContext.getTypeName(childParam.getXMLBridge().getTypeInfo())); aoqi@0: } aoqi@0: } else { aoqi@0: part = message.part().name(param.getPartName()); aoqi@0: part.element(param.getName()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: if (method.getMEP() != MEP.ONE_WAY) { aoqi@0: message = portDefinitions.message().name(method.getResponseMessageName()); aoqi@0: extension.addOutputMessageExtension(message, method); aoqi@0: aoqi@0: for (ParameterImpl param : method.getResponseParameters()) { aoqi@0: if (isDoclit) { aoqi@0: part = message.part().name(param.getPartName()); aoqi@0: part.element(param.getName()); aoqi@0: aoqi@0: } else { aoqi@0: if (param.isWrapperStyle()) { aoqi@0: for (ParameterImpl childParam : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: part = message.part().name(childParam.getPartName()); aoqi@0: part.type(jaxbContext.getTypeName(childParam.getXMLBridge().getTypeInfo())); aoqi@0: } aoqi@0: } else { aoqi@0: part = message.part().name(param.getPartName()); aoqi@0: part.element(param.getName()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { aoqi@0: QName tagName = exception.getDetailType().tagName; aoqi@0: String messageName = exception.getMessageName(); aoqi@0: QName messageQName = new QName(model.getTargetNamespace(), messageName); aoqi@0: if (processedExceptions.contains(messageQName)) aoqi@0: continue; aoqi@0: message = portDefinitions.message().name(messageName); aoqi@0: aoqi@0: extension.addFaultMessageExtension(message, method, exception); aoqi@0: part = message.part().name("fault");//tagName.getLocalPart()); aoqi@0: part.element(tagName); aoqi@0: processedExceptions.add(messageQName); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates the WSDL portType aoqi@0: */ aoqi@0: protected void generatePortType() { aoqi@0: aoqi@0: PortType portType = portDefinitions.portType().name(model.getPortTypeName().getLocalPart()); aoqi@0: extension.addPortTypeExtension(portType); aoqi@0: for (JavaMethodImpl method : model.getJavaMethods()) { aoqi@0: Operation operation = portType.operation().name(method.getOperationName()); aoqi@0: generateParameterOrder(operation, method); aoqi@0: extension.addOperationExtension(operation, method); aoqi@0: switch (method.getMEP()) { aoqi@0: case REQUEST_RESPONSE: aoqi@0: // input message aoqi@0: generateInputMessage(operation, method); aoqi@0: // output message aoqi@0: generateOutputMessage(operation, method); aoqi@0: break; aoqi@0: case ONE_WAY: aoqi@0: generateInputMessage(operation, method); aoqi@0: break; aoqi@0: default: aoqi@0: break; aoqi@0: } aoqi@0: // faults aoqi@0: for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { aoqi@0: QName messageName = new QName(model.getTargetNamespace(), exception.getMessageName()); aoqi@0: FaultType paramType = operation.fault().message(messageName).name(exception.getMessageName()); aoqi@0: extension.addOperationFaultExtension(paramType, method, exception); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Determines if the method is wrapper style aoqi@0: * @param method The {@link JavaMethod} to check if it is wrapper style aoqi@0: * @return true if the method is wrapper style, otherwise, false. aoqi@0: */ aoqi@0: protected boolean isWrapperStyle(JavaMethodImpl method) { aoqi@0: if (method.getRequestParameters().size() > 0) { aoqi@0: ParameterImpl param = method.getRequestParameters().iterator().next(); aoqi@0: return param.isWrapperStyle(); aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Determines if a {@link JavaMethod} is rpc/literal aoqi@0: * @param method The method to check aoqi@0: * @return true if method is rpc/literal, otherwise, false aoqi@0: */ aoqi@0: protected boolean isRpcLit(JavaMethodImpl method) { aoqi@0: return method.getBinding().getStyle() == Style.RPC; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates the parameterOrder for a PortType operation aoqi@0: * @param operation The operation to generate the parameterOrder for aoqi@0: * @param method The {@link JavaMethod} to generate the parameterOrder from aoqi@0: */ aoqi@0: protected void generateParameterOrder(Operation operation, JavaMethodImpl method) { aoqi@0: if (method.getMEP() == MEP.ONE_WAY) aoqi@0: return; aoqi@0: if (isRpcLit(method)) aoqi@0: generateRpcParameterOrder(operation, method); aoqi@0: else aoqi@0: generateDocumentParameterOrder(operation, method); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates the parameterOrder for a PortType operation aoqi@0: * @param operation the operation to generate the parameterOrder for aoqi@0: * @param method the {@link JavaMethod} to generate the parameterOrder from aoqi@0: */ aoqi@0: protected void generateRpcParameterOrder(Operation operation, JavaMethodImpl method) { aoqi@0: String partName; aoqi@0: StringBuilder paramOrder = new StringBuilder(); aoqi@0: Set partNames = new HashSet(); aoqi@0: List sortedParams = sortMethodParameters(method); aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : sortedParams) { aoqi@0: if (parameter.getIndex() >= 0) { aoqi@0: partName = parameter.getPartName(); aoqi@0: if (!partNames.contains(partName)) { aoqi@0: if (i++ > 0) aoqi@0: paramOrder.append(' '); aoqi@0: paramOrder.append(partName); aoqi@0: partNames.add(partName); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: if (i > 1) { aoqi@0: operation.parameterOrder(paramOrder.toString()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Generates the parameterOrder for a PortType operation aoqi@0: * @param operation the operation to generate the parameterOrder for aoqi@0: * @param method the {@link JavaMethod} to generate the parameterOrder from aoqi@0: */ aoqi@0: protected void generateDocumentParameterOrder(Operation operation, JavaMethodImpl method) { aoqi@0: String partName; aoqi@0: StringBuilder paramOrder = new StringBuilder(); aoqi@0: Set partNames = new HashSet(); aoqi@0: List sortedParams = sortMethodParameters(method); aoqi@0: // boolean isWrapperStyle = isWrapperStyle(method); aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : sortedParams) { aoqi@0: // System.out.println("param: "+parameter.getIndex()+" name: "+parameter.getName().getLocalPart()); aoqi@0: if (parameter.getIndex() < 0) aoqi@0: continue; aoqi@0: aoqi@0: // This should be safe change. if it affects compatibility, aoqi@0: // remove the following single statement and uncomment the code in block below. aoqi@0: partName = parameter.getPartName(); aoqi@0: /* aoqi@0: if (isWrapperStyle && isBodyParameter(parameter)) { aoqi@0: System.out.println("isWrapper and is body"); aoqi@0: if (method.getRequestParameters().contains(parameter)) aoqi@0: partName = PARAMETERS; aoqi@0: else { aoqi@0: //Rama: don't understand this logic "Response" below, aoqi@0: aoqi@0: // really make sure this is a wrapper style wsdl we are creating aoqi@0: partName = RESPONSE; aoqi@0: } aoqi@0: } else { aoqi@0: partName = parameter.getPartName(); aoqi@0: }*/ aoqi@0: aoqi@0: if (!partNames.contains(partName)) { aoqi@0: if (i++ > 0) aoqi@0: paramOrder.append(' '); aoqi@0: paramOrder.append(partName); aoqi@0: partNames.add(partName); aoqi@0: } aoqi@0: } aoqi@0: if (i > 1) { aoqi@0: operation.parameterOrder(paramOrder.toString()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Sorts the parameters for the method by their position aoqi@0: * @param method the {@link JavaMethod} used to sort the parameters aoqi@0: * @return the sorted {@link List} of parameters aoqi@0: */ aoqi@0: protected List sortMethodParameters(JavaMethodImpl method) { aoqi@0: Set paramSet = new HashSet(); aoqi@0: List sortedParams = new ArrayList(); aoqi@0: if (isRpcLit(method)) { aoqi@0: for (ParameterImpl param : method.getRequestParameters()) { aoqi@0: if (param instanceof WrapperParameter) { aoqi@0: paramSet.addAll(((WrapperParameter) param).getWrapperChildren()); aoqi@0: } else { aoqi@0: paramSet.add(param); aoqi@0: } aoqi@0: } aoqi@0: for (ParameterImpl param : method.getResponseParameters()) { aoqi@0: if (param instanceof WrapperParameter) { aoqi@0: paramSet.addAll(((WrapperParameter) param).getWrapperChildren()); aoqi@0: } else { aoqi@0: paramSet.add(param); aoqi@0: } aoqi@0: } aoqi@0: } else { aoqi@0: paramSet.addAll(method.getRequestParameters()); aoqi@0: paramSet.addAll(method.getResponseParameters()); aoqi@0: } aoqi@0: Iterator params = paramSet.iterator(); aoqi@0: if (paramSet.isEmpty()) aoqi@0: return sortedParams; aoqi@0: ParameterImpl param = params.next(); aoqi@0: sortedParams.add(param); aoqi@0: ParameterImpl sortedParam; aoqi@0: int pos; aoqi@0: for (int i = 1; i < paramSet.size(); i++) { aoqi@0: param = params.next(); aoqi@0: for (pos = 0; pos < i; pos++) { aoqi@0: sortedParam = sortedParams.get(pos); aoqi@0: if (param.getIndex() == sortedParam.getIndex() && aoqi@0: param instanceof WrapperParameter) aoqi@0: break; aoqi@0: if (param.getIndex() < sortedParam.getIndex()) { aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: sortedParams.add(pos, param); aoqi@0: } aoqi@0: return sortedParams; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Determines if a parameter is associated with the message Body aoqi@0: * @param parameter the parameter to check aoqi@0: * @return true if the parameter is a body parameter aoqi@0: */ aoqi@0: protected boolean isBodyParameter(ParameterImpl parameter) { aoqi@0: ParameterBinding paramBinding = parameter.getBinding(); aoqi@0: return paramBinding.isBody(); aoqi@0: } aoqi@0: aoqi@0: protected boolean isHeaderParameter(ParameterImpl parameter) { aoqi@0: ParameterBinding paramBinding = parameter.getBinding(); aoqi@0: return paramBinding.isHeader(); aoqi@0: } aoqi@0: aoqi@0: protected boolean isAttachmentParameter(ParameterImpl parameter) { aoqi@0: ParameterBinding paramBinding = parameter.getBinding(); aoqi@0: return paramBinding.isAttachment(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Generates the Binding section of the WSDL aoqi@0: */ aoqi@0: protected void generateBinding() { aoqi@0: Binding newBinding = serviceDefinitions.binding().name(model.getBoundPortTypeName().getLocalPart()); aoqi@0: extension.addBindingExtension(newBinding); aoqi@0: newBinding.type(model.getPortTypeName()); aoqi@0: boolean first = true; aoqi@0: for (JavaMethodImpl method : model.getJavaMethods()) { aoqi@0: if (first) { aoqi@0: SOAPBinding sBinding = method.getBinding(); aoqi@0: SOAPVersion soapVersion = sBinding.getSOAPVersion(); aoqi@0: if (soapVersion == SOAPVersion.SOAP_12) { aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPBinding soapBinding = newBinding.soap12Binding(); aoqi@0: soapBinding.transport(this.binding.getBindingId().getTransport()); aoqi@0: if (sBinding.getStyle().equals(Style.DOCUMENT)) aoqi@0: soapBinding.style(DOCUMENT); aoqi@0: else aoqi@0: soapBinding.style(RPC); aoqi@0: } else { aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPBinding soapBinding = newBinding.soapBinding(); aoqi@0: soapBinding.transport(this.binding.getBindingId().getTransport()); aoqi@0: if (sBinding.getStyle().equals(Style.DOCUMENT)) aoqi@0: soapBinding.style(DOCUMENT); aoqi@0: else aoqi@0: soapBinding.style(RPC); aoqi@0: } aoqi@0: first = false; aoqi@0: } aoqi@0: if (this.binding.getBindingId().getSOAPVersion() == SOAPVersion.SOAP_12) aoqi@0: generateSOAP12BindingOperation(method, newBinding); aoqi@0: else aoqi@0: generateBindingOperation(method, newBinding); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void generateBindingOperation(JavaMethodImpl method, Binding binding) { aoqi@0: BindingOperationType operation = binding.operation().name(method.getOperationName()); aoqi@0: extension.addBindingOperationExtension(operation, method); aoqi@0: String targetNamespace = model.getTargetNamespace(); aoqi@0: QName requestMessage = new QName(targetNamespace, method.getOperationName()); aoqi@0: List bodyParams = new ArrayList(); aoqi@0: List headerParams = new ArrayList(); aoqi@0: splitParameters(bodyParams, headerParams, method.getRequestParameters()); aoqi@0: SOAPBinding soapBinding = method.getBinding(); aoqi@0: operation.soapOperation().soapAction(soapBinding.getSOAPAction()); aoqi@0: aoqi@0: // input aoqi@0: TypedXmlWriter input = operation.input(); aoqi@0: extension.addBindingOperationInputExtension(input, method); aoqi@0: BodyType body = input._element(Body.class); aoqi@0: boolean isRpc = soapBinding.getStyle().equals(Style.RPC); aoqi@0: if (soapBinding.getUse() == Use.LITERAL) { aoqi@0: body.use(LITERAL); aoqi@0: if (headerParams.size() > 0) { aoqi@0: if (bodyParams.size() > 0) { aoqi@0: ParameterImpl param = bodyParams.iterator().next(); aoqi@0: if (isRpc) { aoqi@0: StringBuilder parts = new StringBuilder(); aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: if (i++ > 0) aoqi@0: parts.append(' '); aoqi@0: parts.append(parameter.getPartName()); aoqi@0: } aoqi@0: body.parts(parts.toString()); aoqi@0: } else { aoqi@0: body.parts(param.getPartName()); aoqi@0: } aoqi@0: } else { aoqi@0: body.parts(""); aoqi@0: } aoqi@0: generateSOAPHeaders(input, headerParams, requestMessage); aoqi@0: } aoqi@0: if (isRpc) { aoqi@0: body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); aoqi@0: } aoqi@0: } else { aoqi@0: // TODO localize this aoqi@0: throw new WebServiceException("encoded use is not supported"); aoqi@0: } aoqi@0: aoqi@0: if (method.getMEP() != MEP.ONE_WAY) { aoqi@0: // output aoqi@0: bodyParams.clear(); aoqi@0: headerParams.clear(); aoqi@0: splitParameters(bodyParams, headerParams, method.getResponseParameters()); aoqi@0: TypedXmlWriter output = operation.output(); aoqi@0: extension.addBindingOperationOutputExtension(output, method); aoqi@0: body = output._element(Body.class); aoqi@0: body.use(LITERAL); aoqi@0: if (headerParams.size() > 0) { aoqi@0: StringBuilder parts = new StringBuilder(); aoqi@0: if (bodyParams.size() > 0) { aoqi@0: ParameterImpl param = bodyParams.iterator().hasNext() ? bodyParams.iterator().next() : null; aoqi@0: if (param != null) { aoqi@0: if (isRpc) { aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: if (i++ > 0) { aoqi@0: parts.append(" "); aoqi@0: } aoqi@0: parts.append(parameter.getPartName()); aoqi@0: } aoqi@0: } else { aoqi@0: parts = new StringBuilder(param.getPartName()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: body.parts(parts.toString()); aoqi@0: QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); aoqi@0: generateSOAPHeaders(output, headerParams, responseMessage); aoqi@0: } aoqi@0: if (isRpc) { aoqi@0: body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); aoqi@0: } aoqi@0: } aoqi@0: for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { aoqi@0: Fault fault = operation.fault().name(exception.getMessageName()); aoqi@0: extension.addBindingOperationFaultExtension(fault, method, exception); aoqi@0: SOAPFault soapFault = fault._element(SOAPFault.class).name(exception.getMessageName()); aoqi@0: soapFault.use(LITERAL); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void generateSOAP12BindingOperation(JavaMethodImpl method, Binding binding) { aoqi@0: BindingOperationType operation = binding.operation().name(method.getOperationName()); aoqi@0: extension.addBindingOperationExtension(operation, method); aoqi@0: String targetNamespace = model.getTargetNamespace(); aoqi@0: QName requestMessage = new QName(targetNamespace, method.getOperationName()); aoqi@0: ArrayList bodyParams = new ArrayList(); aoqi@0: ArrayList headerParams = new ArrayList(); aoqi@0: splitParameters(bodyParams, headerParams, method.getRequestParameters()); aoqi@0: SOAPBinding soapBinding = method.getBinding(); aoqi@0: aoqi@0: String soapAction = soapBinding.getSOAPAction(); aoqi@0: if (soapAction != null) { aoqi@0: operation.soap12Operation().soapAction(soapAction); aoqi@0: } aoqi@0: aoqi@0: // input aoqi@0: TypedXmlWriter input = operation.input(); aoqi@0: extension.addBindingOperationInputExtension(input, method); aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.soap12.BodyType body = input._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Body.class); aoqi@0: boolean isRpc = soapBinding.getStyle().equals(Style.RPC); aoqi@0: if (soapBinding.getUse().equals(Use.LITERAL)) { aoqi@0: body.use(LITERAL); aoqi@0: if (headerParams.size() > 0) { aoqi@0: if (bodyParams.size() > 0) { aoqi@0: ParameterImpl param = bodyParams.iterator().next(); aoqi@0: if (isRpc) { aoqi@0: StringBuilder parts = new StringBuilder(); aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: if (i++ > 0) aoqi@0: parts.append(' '); aoqi@0: parts.append(parameter.getPartName()); aoqi@0: } aoqi@0: body.parts(parts.toString()); aoqi@0: } else { aoqi@0: body.parts(param.getPartName()); aoqi@0: } aoqi@0: } else { aoqi@0: body.parts(""); aoqi@0: } aoqi@0: generateSOAP12Headers(input, headerParams, requestMessage); aoqi@0: } aoqi@0: if (isRpc) { aoqi@0: body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); aoqi@0: } aoqi@0: } else { aoqi@0: // TODO localize this aoqi@0: throw new WebServiceException("encoded use is not supported"); aoqi@0: } aoqi@0: aoqi@0: if (method.getMEP() != MEP.ONE_WAY) { aoqi@0: // output aoqi@0: bodyParams.clear(); aoqi@0: headerParams.clear(); aoqi@0: splitParameters(bodyParams, headerParams, method.getResponseParameters()); aoqi@0: TypedXmlWriter output = operation.output(); aoqi@0: extension.addBindingOperationOutputExtension(output, method); aoqi@0: body = output._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Body.class); aoqi@0: body.use(LITERAL); aoqi@0: if (headerParams.size() > 0) { aoqi@0: if (bodyParams.size() > 0) { aoqi@0: ParameterImpl param = bodyParams.iterator().next(); aoqi@0: if (isRpc) { aoqi@0: StringBuilder parts = new StringBuilder(); aoqi@0: int i = 0; aoqi@0: for (ParameterImpl parameter : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: if (i++ > 0) { aoqi@0: parts.append(" "); aoqi@0: } aoqi@0: parts.append(parameter.getPartName()); aoqi@0: } aoqi@0: body.parts(parts.toString()); aoqi@0: } else { aoqi@0: body.parts(param.getPartName()); aoqi@0: } aoqi@0: } else { aoqi@0: body.parts(""); aoqi@0: } aoqi@0: QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); aoqi@0: generateSOAP12Headers(output, headerParams, responseMessage); aoqi@0: } aoqi@0: if (isRpc) { aoqi@0: body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); aoqi@0: } aoqi@0: } aoqi@0: for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { aoqi@0: Fault fault = operation.fault().name(exception.getMessageName()); aoqi@0: extension.addBindingOperationFaultExtension(fault, method, exception); aoqi@0: 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()); aoqi@0: soapFault.use(LITERAL); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void splitParameters(List bodyParams, List headerParams, List params) { aoqi@0: for (ParameterImpl parameter : params) { aoqi@0: if (isBodyParameter(parameter)) { aoqi@0: bodyParams.add(parameter); aoqi@0: } else { aoqi@0: headerParams.add(parameter); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void generateSOAPHeaders(TypedXmlWriter writer, List parameters, QName message) { aoqi@0: aoqi@0: for (ParameterImpl headerParam : parameters) { aoqi@0: Header header = writer._element(Header.class); aoqi@0: header.message(message); aoqi@0: header.part(headerParam.getPartName()); aoqi@0: header.use(LITERAL); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void generateSOAP12Headers(TypedXmlWriter writer, List parameters, QName message) { aoqi@0: aoqi@0: for (ParameterImpl headerParam : parameters) { aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header header = writer._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header.class); aoqi@0: header.message(message); aoqi@0: aoqi@0: aoqi@0: header.part(headerParam.getPartName()); aoqi@0: header.use(LITERAL); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Generates the Service section of the WSDL aoqi@0: */ aoqi@0: protected void generateService() { aoqi@0: QName portQName = model.getPortName(); aoqi@0: QName serviceQName = model.getServiceQName(); aoqi@0: Service service = serviceDefinitions.service().name(serviceQName.getLocalPart()); aoqi@0: extension.addServiceExtension(service); aoqi@0: Port port = service.port().name(portQName.getLocalPart()); aoqi@0: port.binding(model.getBoundPortTypeName()); aoqi@0: extension.addPortExtension(port); aoqi@0: if (model.getJavaMethods().isEmpty()) aoqi@0: return; aoqi@0: aoqi@0: if (this.binding.getBindingId().getSOAPVersion() == SOAPVersion.SOAP_12) { aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress address = port._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress.class); aoqi@0: address.location(endpointAddress); aoqi@0: } else { aoqi@0: SOAPAddress address = port._element(SOAPAddress.class); aoqi@0: address.location(endpointAddress); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void generateInputMessage(Operation operation, JavaMethodImpl method) { aoqi@0: ParamType paramType = operation.input(); aoqi@0: extension.addOperationInputExtension(paramType, method); aoqi@0: // paramType.message(method.getOperation().getName()); aoqi@0: paramType.message(new QName(model.getTargetNamespace(), method.getRequestMessageName())); aoqi@0: } aoqi@0: aoqi@0: protected void generateOutputMessage(Operation operation, JavaMethodImpl method) { aoqi@0: ParamType paramType = operation.output(); aoqi@0: extension.addOperationOutputExtension(paramType, method); aoqi@0: // paramType.message(new QName(model.getTargetNamespace(), method.getOperation().getLocalName()+RESPONSE)); aoqi@0: paramType.message(new QName(model.getTargetNamespace(), method.getResponseMessageName())); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Creates the {@link Result} object used by JAXB to generate a schema for the aoqi@0: * namesapceUri namespace. aoqi@0: * @param namespaceUri The namespace for the schema being generated aoqi@0: * @param suggestedFileName the JAXB suggested file name for the schema file aoqi@0: * @return the {@link Result} for JAXB to generate the schema into aoqi@0: * @throws java.io.IOException thrown if on IO error occurs aoqi@0: */ aoqi@0: public Result createOutputFile(String namespaceUri, String suggestedFileName) throws IOException { aoqi@0: Result result; aoqi@0: if (namespaceUri == null) { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: Holder fileNameHolder = new Holder(); aoqi@0: fileNameHolder.value = schemaPrefix + suggestedFileName; aoqi@0: result = wsdlResolver.getSchemaOutput(namespaceUri, fileNameHolder); aoqi@0: // System.out.println("schema file: "+fileNameHolder.value); aoqi@0: // System.out.println("result: "+result); aoqi@0: String schemaLoc; aoqi@0: if (result == null) aoqi@0: schemaLoc = fileNameHolder.value; aoqi@0: else aoqi@0: schemaLoc = relativize(result.getSystemId(), wsdlLocation); aoqi@0: boolean isEmptyNs = namespaceUri.trim().equals(""); aoqi@0: if (!isEmptyNs) { aoqi@0: com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import(); aoqi@0: _import.namespace(namespaceUri); aoqi@0: _import.schemaLocation(schemaLoc); aoqi@0: } aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: private Result createInlineSchema(String namespaceUri, String suggestedFileName) throws IOException { aoqi@0: Result result; aoqi@0: if (namespaceUri.equals("")) { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: // Holder fileNameHolder = new Holder(); aoqi@0: // fileNameHolder.value = schemaPrefix+suggestedFileName; aoqi@0: // result = wsdlResolver.getSchemaOutput(namespaceUri, fileNameHolder); aoqi@0: // if (result == null) { aoqi@0: // // JAXB doesn't have to generate it, a schema is already available aoqi@0: // com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import().namespace(namespaceUri); aoqi@0: // _import.schemaLocation(fileNameHolder.value); aoqi@0: // } else { aoqi@0: // Let JAXB write the schema directly into wsdl's TypedXmlWriter aoqi@0: result = new TXWResult(types); aoqi@0: result.setSystemId(""); aoqi@0: // } aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Relativizes a URI by using another URI (base URI.) aoqi@0: * aoqi@0: *

aoqi@0: * For example, {@code relative("http://www.sun.com/abc/def","http://www.sun.com/pqr/stu") => "../abc/def"} aoqi@0: * aoqi@0: *

aoqi@0: * This method only works on hierarchical URI's, not opaque URI's (refer to the aoqi@0: * java.net.URI aoqi@0: * javadoc for complete definitions of these terms. aoqi@0: * aoqi@0: *

aoqi@0: * This method will not normalize the relative URI. aoqi@0: * @param uri the URI to relativize aoqi@0: * aoqi@0: * aoqi@0: * @param baseUri the base URI to use for the relativization aoqi@0: * @return the relative URI or the original URI if a relative one could not be computed aoqi@0: */ aoqi@0: protected static String relativize(String uri, String baseUri) { aoqi@0: try { aoqi@0: assert uri != null; aoqi@0: aoqi@0: if (baseUri == null) return uri; aoqi@0: aoqi@0: URI theUri = new URI(escapeURI(uri)); aoqi@0: URI theBaseUri = new URI(escapeURI(baseUri)); aoqi@0: aoqi@0: if (theUri.isOpaque() || theBaseUri.isOpaque()) aoqi@0: return uri; aoqi@0: aoqi@0: if (!equalsIgnoreCase(theUri.getScheme(), theBaseUri.getScheme()) || aoqi@0: !equal(theUri.getAuthority(), theBaseUri.getAuthority())) aoqi@0: return uri; aoqi@0: aoqi@0: String uriPath = theUri.getPath(); aoqi@0: String basePath = theBaseUri.getPath(); aoqi@0: aoqi@0: // normalize base path aoqi@0: if (!basePath.endsWith("/")) { aoqi@0: basePath = normalizeUriPath(basePath); aoqi@0: } aoqi@0: aoqi@0: if (uriPath.equals(basePath)) aoqi@0: return "."; aoqi@0: aoqi@0: String relPath = calculateRelativePath(uriPath, basePath); aoqi@0: aoqi@0: if (relPath == null) aoqi@0: return uri; // recursion found no commonality in the two uris at all aoqi@0: StringBuilder relUri = new StringBuilder(); aoqi@0: relUri.append(relPath); aoqi@0: if (theUri.getQuery() != null) aoqi@0: relUri.append('?').append(theUri.getQuery()); aoqi@0: if (theUri.getFragment() != null) aoqi@0: relUri.append('#').append(theUri.getFragment()); aoqi@0: aoqi@0: return relUri.toString(); aoqi@0: } catch (URISyntaxException e) { aoqi@0: throw new InternalError("Error escaping one of these uris:\n\t" + uri + "\n\t" + baseUri); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static String calculateRelativePath(String uri, String base) { aoqi@0: if (base == null) { aoqi@0: return null; aoqi@0: } aoqi@0: if (uri.startsWith(base)) { aoqi@0: return uri.substring(base.length()); aoqi@0: } else { aoqi@0: return "../" + calculateRelativePath(uri, getParentUriPath(base)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Implements the SchemaOutputResolver used by JAXB to aoqi@0: */ aoqi@0: protected class JAXWSOutputSchemaResolver extends SchemaOutputResolver { aoqi@0: ArrayList nonGlassfishSchemas = null; aoqi@0: aoqi@0: /** aoqi@0: * Creates the {@link Result} object used by JAXB to generate a schema for the aoqi@0: * namesapceUri namespace. aoqi@0: * @param namespaceUri The namespace for the schema being generated aoqi@0: * @param suggestedFileName the JAXB suggested file name for the schema file aoqi@0: * @return the {@link Result} for JAXB to generate the schema into aoqi@0: * @throws java.io.IOException thrown if on IO error occurs aoqi@0: */ aoqi@0: @Override aoqi@0: public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { aoqi@0: return inlineSchemas aoqi@0: ? ((nonGlassfishSchemas != null) ? nonGlassfishSchemaResult(namespaceUri, suggestedFileName) : createInlineSchema(namespaceUri, suggestedFileName)) aoqi@0: // ? createInlineSchema(namespaceUri, suggestedFileName) aoqi@0: : createOutputFile(namespaceUri, suggestedFileName); aoqi@0: } aoqi@0: aoqi@0: private Result nonGlassfishSchemaResult(String namespaceUri, String suggestedFileName) throws IOException { aoqi@0: DOMResult result = new DOMResult(); aoqi@0: result.setSystemId(""); aoqi@0: nonGlassfishSchemas.add(result); aoqi@0: return result; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void register(WSDLGeneratorExtension h) { aoqi@0: extensionHandlers.add(h); aoqi@0: } aoqi@0: }