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

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

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

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