com.sun.xml.ws.wsdl.writer.WSDLGenerator Maven / Gradle / Ivy
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.xml.ws.wsdl.writer; import com.sun.xml.bind.api.JAXBRIContext; import static com.sun.xml.bind.v2.schemagen.Util.*; import com.sun.xml.txw2.TXW; import com.sun.xml.txw2.TypedXmlWriter; import com.sun.xml.txw2.output.ResultFactory; import com.sun.xml.txw2.output.XmlSerializer; import com.sun.xml.ws.api.SOAPVersion; import com.sun.xml.ws.api.WSBinding; import com.sun.xml.ws.api.model.JavaMethod; import com.sun.xml.ws.api.model.MEP; import com.sun.xml.ws.api.model.ParameterBinding; import com.sun.xml.ws.api.model.SEIModel; import com.sun.xml.ws.api.model.soap.SOAPBinding; import com.sun.xml.ws.api.server.Container; import com.sun.xml.ws.api.wsdl.writer.WSDLGeneratorExtension; import com.sun.xml.ws.api.wsdl.writer.WSDLGenExtnContext; import com.sun.xml.ws.encoding.soap.streaming.SOAP12NamespaceConstants; import com.sun.xml.ws.encoding.soap.streaming.SOAPNamespaceConstants; import com.sun.xml.ws.model.AbstractSEIModelImpl; import com.sun.xml.ws.model.CheckedExceptionImpl; import com.sun.xml.ws.model.JavaMethodImpl; import com.sun.xml.ws.model.ParameterImpl; import com.sun.xml.ws.model.WrapperParameter; import com.sun.xml.ws.wsdl.parser.SOAPConstants; import com.sun.xml.ws.wsdl.parser.WSDLConstants; import com.sun.xml.ws.wsdl.writer.document.Binding; import com.sun.xml.ws.wsdl.writer.document.BindingOperationType; import com.sun.xml.ws.wsdl.writer.document.Definitions; import com.sun.xml.ws.wsdl.writer.document.Fault; import com.sun.xml.ws.wsdl.writer.document.FaultType; import com.sun.xml.ws.wsdl.writer.document.Import; import com.sun.xml.ws.wsdl.writer.document.Message; import com.sun.xml.ws.wsdl.writer.document.Operation; import com.sun.xml.ws.wsdl.writer.document.ParamType; import com.sun.xml.ws.wsdl.writer.document.Port; import com.sun.xml.ws.wsdl.writer.document.PortType; import com.sun.xml.ws.wsdl.writer.document.Service; import com.sun.xml.ws.wsdl.writer.document.Types; import com.sun.xml.ws.wsdl.writer.document.soap.Body; import com.sun.xml.ws.wsdl.writer.document.soap.BodyType; import com.sun.xml.ws.wsdl.writer.document.soap.Header; import com.sun.xml.ws.wsdl.writer.document.soap.SOAPAddress; import com.sun.xml.ws.wsdl.writer.document.soap.SOAPFault; import com.sun.xml.ws.util.RuntimeVersion; import javax.jws.soap.SOAPBinding.Style; import javax.jws.soap.SOAPBinding.Use; import javax.xml.bind.SchemaOutputResolver; import javax.xml.namespace.QName; import javax.xml.transform.Result; import javax.xml.ws.Holder; import javax.xml.ws.WebServiceException; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Class used to generate WSDLs from a {@link SEIModel}. * * @author WS Development Team */ public class WSDLGenerator { private JAXWSOutputSchemaResolver resolver; private WSDLResolver wsdlResolver = null; private AbstractSEIModelImpl model; private Definitions serviceDefinitions; private Definitions portDefinitions; private Types types; /** * Constant String for ".wsdl" */ private static final String DOT_WSDL = ".wsdl"; /** * Constant String appended to response message names */ private static final String RESPONSE = "Response"; /** * constant String used for part name for wrapped request messages */ private static final String PARAMETERS = "parameters"; /** * the part name for unwrappable response messages */ private static final String RESULT = "parameters"; /** * the part name for response messages that are not unwrappable */ private static final String UNWRAPPABLE_RESULT = "result"; /** * The WSDL namespace */ private static final String WSDL_NAMESPACE = WSDLConstants.NS_WSDL; /** * the XSD namespace */ private static final String XSD_NAMESPACE = SOAPNamespaceConstants.XSD; /** * the namespace prefix to use for the XSD namespace */ private static final String XSD_PREFIX = "xsd"; /** * The SOAP 1.1 namespace */ private static final String SOAP11_NAMESPACE = SOAPConstants.NS_WSDL_SOAP; /** * The SOAP 1.2 namespace */ private static final String SOAP12_NAMESPACE = SOAPConstants.NS_WSDL_SOAP12; /** * The namespace prefix to use for the SOAP 1.1 namespace */ private static final String SOAP_PREFIX = "soap"; /** * The namespace prefix to use for the SOAP 1.2 namespace */ private static final String SOAP12_PREFIX = "soap12"; /** * The namespace prefix to use for the targetNamespace */ private static final String TNS_PREFIX = "tns"; /** * The URI for the SOAP 1.1 HTTP Transport. Used to create soapBindings */ private static final String SOAP_HTTP_TRANSPORT = SOAPNamespaceConstants.TRANSPORT_HTTP; /** * The URI for the SOAP 1.2 HTTP Transport. Used to create soapBindings */ private static final String SOAP12_HTTP_TRANSPORT = SOAP12NamespaceConstants.TRANSPORT_HTTP; /** * Constant String "document" used to specify
parameter */ protected boolean isBodyParameter(ParameterImpl parameter) { ParameterBinding paramBinding = parameter.getBinding(); return paramBinding.isBody(); } protected boolean isHeaderParameter(ParameterImpl parameter) { ParameterBinding paramBinding = parameter.getBinding(); return paramBinding.isHeader(); } protected boolean isAttachmentParameter(ParameterImpl parameter) { ParameterBinding paramBinding = parameter.getBinding(); return paramBinding.isAttachment(); } /** * Generates the Binding section of the WSDL */ protected void generateBinding() { Binding binding = serviceDefinitions.binding().name(model.getBoundPortTypeName().getLocalPart()); extension.addBindingExtension(binding); binding.type(model.getPortTypeName()); boolean first = true; for (JavaMethodImpl method : model.getJavaMethods()) { if (first) { SOAPBinding sBinding = method.getBinding(); SOAPVersion soapVersion = sBinding.getSOAPVersion(); if (soapVersion == SOAPVersion.SOAP_12){ com.sun.xml.ws.wsdl.writer.document.soap12.SOAPBinding soapBinding = binding.soap12Binding(); soapBinding.transport(this.binding.getBindingId().getTransport()); if (sBinding.getStyle().equals(Style.DOCUMENT)) soapBinding.style(DOCUMENT); else soapBinding.style(RPC); } else { com.sun.xml.ws.wsdl.writer.document.soap.SOAPBinding soapBinding = binding.soapBinding(); soapBinding.transport(this.binding.getBindingId().getTransport()); if (sBinding.getStyle().equals(Style.DOCUMENT)) soapBinding.style(DOCUMENT); else soapBinding.style(RPC); } first = false; } if(this.binding.getBindingId().getSOAPVersion()==SOAPVersion.SOAP_12) generateSOAP12BindingOperation(method, binding); else generateBindingOperation(method, binding); } } protected void generateBindingOperation(JavaMethodImpl method, Binding binding) { BindingOperationType operation = binding.operation().name(method.getOperationName()); extension.addBindingOperationExtension(operation, method); String targetNamespace = model.getTargetNamespace(); QName requestMessage = new QName(targetNamespace, method.getOperationName()); Listdocument
style * soapBindings */ private static final String DOCUMENT = "document"; /** * Constant String "rpc" used to specifyrpc
style * soapBindings */ private static final String RPC = "rpc"; /** * Constant String "literal" used to createliteral
use binddings */ private static final String LITERAL = "literal"; /** * Constant String to flag the URL to replace at runtime for the endpoint */ private static final String REPLACE_WITH_ACTUAL_URL = "REPLACE_WITH_ACTUAL_URL"; private SetprocessedExceptions = new HashSet (); private WSBinding binding; private String wsdlLocation; private String portWSDLID; private String schemaPrefix; private WSDLGeneratorExtension extension; List extensionHandlers; private String endpointAddress = REPLACE_WITH_ACTUAL_URL; private Container container; private final Class implType; /** * Creates the WSDLGenerator * @param model The {@link AbstractSEIModelImpl} used to generate the WSDL * @param wsdlResolver The {@link WSDLResolver} to use resovle names while generating the WSDL * @param binding specifies which {@link javax.xml.ws.BindingType} to generate * @param extensions an array {@link WSDLGeneratorExtension} that will * be invoked to generate WSDL extensions */ public WSDLGenerator(AbstractSEIModelImpl model, WSDLResolver wsdlResolver, WSBinding binding, Container container, Class implType, WSDLGeneratorExtension... extensions) { this.model = model; resolver = new JAXWSOutputSchemaResolver(); this.wsdlResolver = wsdlResolver; this.binding = binding; this.container = container; this.implType = implType; extensionHandlers = new ArrayList (); // register handlers for default extensions register(new W3CAddressingWSDLGeneratorExtension()); for (WSDLGeneratorExtension w : extensions) register(w); this.extension = new WSDLGeneratorExtensionFacade(extensionHandlers.toArray(new WSDLGeneratorExtension[0])); } /** * Sets the endpoint address string to be written. * Defaults to {@link #REPLACE_WITH_ACTUAL_URL}. */ public void setEndpointAddress(String address) { this.endpointAddress = address; } /** * Performes the actual WSDL generation */ public void doGeneration() { XmlSerializer serviceWriter; XmlSerializer portWriter = null; String fileName = JAXBRIContext.mangleNameToClassName(model.getServiceQName().getLocalPart()); Result result = wsdlResolver.getWSDL(fileName+DOT_WSDL); wsdlLocation = result.getSystemId(); serviceWriter = new CommentFilter(ResultFactory.createSerializer(result)); if (model.getServiceQName().getNamespaceURI().equals(model.getTargetNamespace())) { portWriter = serviceWriter; schemaPrefix = fileName+"_"; } else { String wsdlName = JAXBRIContext.mangleNameToClassName(model.getPortTypeName().getLocalPart()); if (wsdlName.equals(fileName)) wsdlName += "PortType"; Holder absWSDLName = new Holder (); absWSDLName.value = wsdlName+DOT_WSDL; result = wsdlResolver.getAbstractWSDL(absWSDLName); if (result != null) { portWSDLID = result.getSystemId(); if (portWSDLID.equals(wsdlLocation)) { portWriter = serviceWriter; } else { portWriter = new CommentFilter(ResultFactory.createSerializer(result)); } } else { portWSDLID = absWSDLName.value; } schemaPrefix = new java.io.File(portWSDLID).getName(); int idx = schemaPrefix.lastIndexOf('.'); if (idx > 0) schemaPrefix = schemaPrefix.substring(0, idx); schemaPrefix = JAXBRIContext.mangleNameToClassName(schemaPrefix)+"_"; } generateDocument(serviceWriter, portWriter); } /** * Writing directly to XmlSerializer is a problem, since it doesn't suppress * xml declaration. Creating filter so that comment is written before TXW writes * anything in the WSDL. */ private static class CommentFilter implements XmlSerializer { final XmlSerializer serializer; private static final String VERSION_COMMENT = " Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is "+RuntimeVersion.VERSION+". "; CommentFilter(XmlSerializer serializer) { this.serializer = serializer; } public void startDocument() { serializer.startDocument(); comment(new StringBuilder(VERSION_COMMENT)); text(new StringBuilder("\n")); } public void beginStartTag(String uri, String localName, String prefix) { serializer.beginStartTag(uri, localName, prefix); } public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) { serializer.writeAttribute(uri, localName, prefix, value); } public void writeXmlns(String prefix, String uri) { serializer.writeXmlns(prefix, uri); } public void endStartTag(String uri, String localName, String prefix) { serializer.endStartTag(uri, localName, prefix); } public void endTag() { serializer.endTag(); } public void text(StringBuilder text) { serializer.text(text); } public void cdata(StringBuilder text) { serializer.cdata(text); } public void comment(StringBuilder comment) { serializer.comment(comment); } public void endDocument() { serializer.endDocument(); } public void flush() { serializer.flush(); } } private void generateDocument(XmlSerializer serviceStream, XmlSerializer portStream) { serviceDefinitions = TXW.create(Definitions.class, serviceStream); serviceDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); serviceDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); serviceDefinitions.targetNamespace(model.getServiceQName().getNamespaceURI()); serviceDefinitions._namespace(model.getServiceQName().getNamespaceURI(), TNS_PREFIX); if(binding.getSOAPVersion()== SOAPVersion.SOAP_12) serviceDefinitions._namespace(SOAP12_NAMESPACE, SOAP12_PREFIX); else serviceDefinitions._namespace(SOAP11_NAMESPACE, SOAP_PREFIX); serviceDefinitions.name(model.getServiceQName().getLocalPart()); WSDLGenExtnContext serviceCtx = new WSDLGenExtnContext(serviceDefinitions, model, binding, container, implType); extension.start(serviceCtx); if (serviceStream != portStream && portStream != null) { // generate an abstract and concrete wsdl portDefinitions = TXW.create(Definitions.class, portStream); portDefinitions._namespace(WSDL_NAMESPACE, "");//WSDL_PREFIX); portDefinitions._namespace(XSD_NAMESPACE, XSD_PREFIX); if (model.getTargetNamespace() != null) { portDefinitions.targetNamespace(model.getTargetNamespace()); portDefinitions._namespace(model.getTargetNamespace(), TNS_PREFIX); } String schemaLoc = relativize(portWSDLID, wsdlLocation); Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); _import.location(schemaLoc); } else if (portStream != null) { // abstract and concrete are the same portDefinitions = serviceDefinitions; } else { // import a provided abstract wsdl String schemaLoc = relativize(portWSDLID, wsdlLocation); Import _import = serviceDefinitions._import().namespace(model.getTargetNamespace()); _import.location(schemaLoc); } extension.addDefinitionsExtension(serviceDefinitions); if (portDefinitions != null) { generateTypes(); generateMessages(); generatePortType(); } generateBinding(); generateService(); //Give a chance to WSDLGeneratorExtensions to write stuff before closing extension.end(serviceCtx); serviceDefinitions.commit(); if (portDefinitions != null && portDefinitions != serviceDefinitions) portDefinitions.commit(); } /** * Generates the types section of the WSDL */ protected void generateTypes() { types = portDefinitions.types(); if (model.getJAXBContext() != null) { try { model.getJAXBContext().generateSchema(resolver); } catch (IOException e) { // TODO locallize and wrap this e.printStackTrace(); throw new WebServiceException(e.getMessage()); } } } /** * Generates the WSDL messages */ protected void generateMessages() { for (JavaMethodImpl method : model.getJavaMethods()) { generateSOAPMessages(method, method.getBinding()); } } /** * Generates messages for a SOAPBinding * @param method The {@link JavaMethod} to generate messages for * @param binding The {@link com.sun.xml.ws.api.model.soap.SOAPBinding} to add the generated messages to */ protected void generateSOAPMessages(JavaMethodImpl method, com.sun.xml.ws.api.model.soap.SOAPBinding binding) { boolean isDoclit = binding.isDocLit(); // Message message = portDefinitions.message().name(method.getOperation().getName().getLocalPart()); Message message = portDefinitions.message().name(method.getRequestMessageName()); extension.addInputMessageExtension(message, method); com.sun.xml.ws.wsdl.writer.document.Part part; JAXBRIContext jaxbContext = model.getJAXBContext(); boolean unwrappable = true; for (ParameterImpl param : method.getRequestParameters()) { if (isDoclit) { if (isHeaderParameter(param)) unwrappable = false; if (param.isWrapperStyle()) { part = message.part().name(PARAMETERS); part.element(param.getName()); } else { part = message.part().name(param.getPartName()); part.element(param.getName()); } } else { if (param.isWrapperStyle()) { for (ParameterImpl childParam : ((WrapperParameter)param).getWrapperChildren()) { part = message.part().name(childParam.getPartName()); part.type(jaxbContext.getTypeName(childParam.getBridge().getTypeReference())); } } else { part = message.part().name(param.getPartName()); part.element(param.getName()); } } } if (method.getMEP() != MEP.ONE_WAY) { // message = portDefinitions.message().name(method.getOperation().getName().getLocalPart()+RESPONSE); message = portDefinitions.message().name(method.getResponseMessageName()); extension.addOutputMessageExtension(message, method); if (unwrappable) { for (ParameterImpl param : method.getResponseParameters()) { if (isHeaderParameter(param)) unwrappable = false; } } for (ParameterImpl param : method.getResponseParameters()) { if (isDoclit) { if (param.isWrapperStyle()) { // if its not really wrapper style dont use the same name as input message if (unwrappable) part = message.part().name(RESULT); else part = message.part().name(UNWRAPPABLE_RESULT); part.element(param.getName()); } else { part = message.part().name(param.getPartName()); part.element(param.getName()); } } else { if (param.isWrapperStyle()) { for (ParameterImpl childParam : ((WrapperParameter)param).getWrapperChildren()) { part = message.part().name(childParam.getPartName()); part.type(jaxbContext.getTypeName(childParam.getBridge().getTypeReference())); } } else { part = message.part().name(param.getPartName()); part.element(param.getName()); } } } } for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { QName tagName = exception.getDetailType().tagName; String messageName = exception.getMessageName(); QName messageQName = new QName(model.getTargetNamespace(), messageName); if (processedExceptions.contains(messageQName)) continue; message = portDefinitions.message().name(messageName); extension.addFaultMessageExtension(message, method, exception); part = message.part().name("fault");//tagName.getLocalPart()); part.element(tagName); processedExceptions.add(messageQName); } } /** * Generates the WSDL portType */ protected void generatePortType() { PortType portType = portDefinitions.portType().name(model.getPortTypeName().getLocalPart()); extension.addPortTypeExtension(portType); for (JavaMethodImpl method : model.getJavaMethods()) { Operation operation = portType.operation().name(method.getOperationName()); generateParameterOrder(operation, method); extension.addOperationExtension(operation, method); switch (method.getMEP()) { case REQUEST_RESPONSE: // input message generateInputMessage(operation, method); // output message generateOutputMessage(operation, method); break; case ONE_WAY: generateInputMessage(operation, method); break; } // faults for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { QName messageName = new QName(model.getTargetNamespace(), exception.getMessageName()); FaultType paramType = operation.fault().message(messageName).name(exception.getMessageName()); extension.addOperationFaultExtension(paramType, method, exception); } } } /** * Determines if the method
is wrapper style * @param method The {@link JavaMethod} to check if it is wrapper style * @return true if the method is wrapper style, otherwise, false. */ protected boolean isWrapperStyle(JavaMethodImpl method) { if (method.getRequestParameters().size() > 0) { ParameterImpl param = method.getRequestParameters().iterator().next(); return param.isWrapperStyle(); } return false; } /** * Determines if a {@link JavaMethod} is rpc/literal * @param method The method to check * @return true if method is rpc/literal, otherwise, false */ protected boolean isRpcLit(JavaMethodImpl method) { return method.getBinding().getStyle() == Style.RPC; } /** * Generates the parameterOrder for a PortType operation * @param operation The operation to generate the parameterOrder for * @param method The {@link JavaMethod} to generate the parameterOrder from */ protected void generateParameterOrder(Operation operation, JavaMethodImpl method) { if (method.getMEP() == MEP.ONE_WAY) return; if (isRpcLit(method)) generateRpcParameterOrder(operation, method); else generateDocumentParameterOrder(operation, method); } /** * Generates the parameterOrder for a PortType operation * @param operation the operation to generate the parameterOrder for * @param method the {@link JavaMethod} to generate the parameterOrder from */ protected void generateRpcParameterOrder(Operation operation, JavaMethodImpl method) { String partName; StringBuffer paramOrder = new StringBuffer(); SetpartNames = new HashSet (); List sortedParams = sortMethodParameters(method); int i = 0; for (ParameterImpl parameter : sortedParams) { if (parameter.getIndex() >= 0) { partName = parameter.getPartName(); if (!partNames.contains(partName)) { if (i++ > 0) paramOrder.append(' '); paramOrder.append(partName); partNames.add(partName); } } } if (i>1) { operation.parameterOrder(paramOrder.toString()); } } /** * Generates the parameterOrder for a PortType operation * @param operation the operation to generate the parameterOrder for * @param method the {@link JavaMethod} to generate the parameterOrder from */ protected void generateDocumentParameterOrder(Operation operation, JavaMethodImpl method) { String partName; StringBuffer paramOrder = new StringBuffer(); Set partNames = new HashSet (); List sortedParams = sortMethodParameters(method); boolean isWrapperStyle = isWrapperStyle(method); int i = 0; for (ParameterImpl parameter : sortedParams) { // System.out.println("param: "+parameter.getIndex()+" name: "+parameter.getName().getLocalPart()); if (parameter.getIndex() < 0) continue; if (isWrapperStyle && isBodyParameter(parameter)) { // System.out.println("isWrapper and is body"); if (method.getRequestParameters().contains(parameter)) partName = PARAMETERS; else { // really make sure this is a wrapper style wsdl we are creating partName = RESPONSE; } } else { partName = parameter.getPartName(); } if (!partNames.contains(partName)) { if (i++ > 0) paramOrder.append(' '); paramOrder.append(partName); partNames.add(partName); } } if (i>1) { operation.parameterOrder(paramOrder.toString()); } } /** * Sorts the parameters for the method by their position * @param method the {@link JavaMethod} used to sort the parameters * @return the sorted {@link List} of parameters */ protected List sortMethodParameters(JavaMethodImpl method) { Set paramSet = new HashSet (); List sortedParams = new ArrayList (); if (isRpcLit(method)) { for (ParameterImpl param : method.getRequestParameters()) { if (param instanceof WrapperParameter) { paramSet.addAll(((WrapperParameter)param).getWrapperChildren()); } else { paramSet.add(param); } } for (ParameterImpl param : method.getResponseParameters()) { if (param instanceof WrapperParameter) { paramSet.addAll(((WrapperParameter)param).getWrapperChildren()); } else { paramSet.add(param); } } } else { paramSet.addAll(method.getRequestParameters()); paramSet.addAll(method.getResponseParameters()); } Iterator params = paramSet.iterator(); if (paramSet.size() == 0) return sortedParams; ParameterImpl param = params.next(); sortedParams.add(param); ParameterImpl sortedParam; int pos; for (int i=1; i body bodyParams = new ArrayList (); List headerParams = new ArrayList (); splitParameters(bodyParams, headerParams, method.getRequestParameters()); SOAPBinding soapBinding = method.getBinding(); operation.soapOperation().soapAction(soapBinding.getSOAPAction()); // input TypedXmlWriter input = operation.input(); extension.addBindingOperationInputExtension(input, method); BodyType body = input._element(Body.class); boolean isRpc = soapBinding.getStyle().equals(Style.RPC); if (soapBinding.getUse()==Use.LITERAL) { body.use(LITERAL); if (headerParams.size() > 0) { if (bodyParams.size() > 0) { ParameterImpl param = bodyParams.iterator().next(); if (isRpc) { StringBuffer parts = new StringBuffer(); int i=0; for (ParameterImpl parameter : ((WrapperParameter)param).getWrapperChildren()) { if (i++>0) parts.append(' '); parts.append(parameter.getPartName()); } body.parts(parts.toString()); } else if (param.isWrapperStyle()) { body.parts(PARAMETERS); } else { body.parts(param.getPartName()); } } else { body.parts(""); } generateSOAPHeaders(input, headerParams, requestMessage); } if (isRpc) { body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); } } else { // TODO localize this throw new WebServiceException("encoded use is not supported"); } if (method.getMEP() != MEP.ONE_WAY) { boolean unwrappable = headerParams.size() == 0; // output bodyParams.clear(); headerParams.clear(); splitParameters(bodyParams, headerParams, method.getResponseParameters()); unwrappable = unwrappable ? headerParams.size() == 0 : unwrappable; TypedXmlWriter output = operation.output(); extension.addBindingOperationOutputExtension(output, method); body = output._element(Body.class); body.use(LITERAL); if (headerParams.size() > 0) { String parts = ""; if (bodyParams.size() > 0) { ParameterImpl param = bodyParams.iterator().hasNext() ? bodyParams.iterator().next() : null; if(param!=null){ if (isRpc) { int i=0; for (ParameterImpl parameter : ((WrapperParameter)param).getWrapperChildren()) { if (i++>0) parts += " "; parts += parameter.getPartName(); } } else { if (param.isWrapperStyle()) { // if its not really wrapper style dont use the same name as input message if (unwrappable) parts = RESULT; else parts = UNWRAPPABLE_RESULT; } else { parts = param.getPartName(); } } } } body.parts(parts); QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); generateSOAPHeaders(output, headerParams, responseMessage); } if (isRpc) { body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); } } for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { Fault fault = operation.fault().name(exception.getMessageName()); extension.addBindingOperationFaultExtension(fault, method, exception); SOAPFault soapFault = fault._element(SOAPFault.class).name(exception.getMessageName()); soapFault.use(LITERAL); } } protected void generateSOAP12BindingOperation(JavaMethodImpl method, Binding binding) { BindingOperationType operation = binding.operation().name(method.getOperationName()); extension.addBindingOperationExtension(operation, method); String targetNamespace = model.getTargetNamespace(); QName requestMessage = new QName(targetNamespace, method.getOperationName()); ArrayList bodyParams = new ArrayList (); ArrayList headerParams = new ArrayList (); splitParameters(bodyParams, headerParams, method.getRequestParameters()); SOAPBinding soapBinding = method.getBinding(); operation.soap12Operation().soapAction(soapBinding.getSOAPAction()); // input TypedXmlWriter input = operation.input(); extension.addBindingOperationInputExtension(input, method); com.sun.xml.ws.wsdl.writer.document.soap12.BodyType body = input._element(com.sun.xml.ws.wsdl.writer.document.soap12.Body.class); boolean isRpc = soapBinding.getStyle().equals(Style.RPC); if (soapBinding.getUse().equals(Use.LITERAL)) { body.use(LITERAL); if (headerParams.size() > 0) { if (bodyParams.size() > 0) { ParameterImpl param = bodyParams.iterator().next(); if (isRpc) { StringBuffer parts = new StringBuffer(); int i=0; for (ParameterImpl parameter : ((WrapperParameter)param).getWrapperChildren()) { if (i++>0) parts.append(' '); parts.append(parameter.getPartName()); } body.parts(parts.toString()); } else if (param.isWrapperStyle()) { body.parts(PARAMETERS); } else { body.parts(param.getPartName()); } } else { body.parts(""); } generateSOAP12Headers(input, headerParams, requestMessage); } if (isRpc) { body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); } } else { // TODO localize this throw new WebServiceException("encoded use is not supported"); } if (method.getMEP() != MEP.ONE_WAY) { // output boolean unwrappable = headerParams.size() == 0; bodyParams.clear(); headerParams.clear(); splitParameters(bodyParams, headerParams, method.getResponseParameters()); unwrappable = unwrappable ? headerParams.size() == 0 : unwrappable; TypedXmlWriter output = operation.output(); extension.addBindingOperationOutputExtension(output, method); body = output._element(com.sun.xml.ws.wsdl.writer.document.soap12.Body.class); body.use(LITERAL); if (headerParams.size() > 0) { if (bodyParams.size() > 0) { ParameterImpl param = bodyParams.iterator().next(); if (isRpc) { String parts = ""; int i=0; for (ParameterImpl parameter : ((WrapperParameter)param).getWrapperChildren()) { if (i++>0) parts += " "; parts += parameter.getPartName(); } body.parts(parts); } else if (param.isWrapperStyle()) { // if its not really wrapper style dont use the same name as input message if (unwrappable) body.parts(RESULT); else body.parts(UNWRAPPABLE_RESULT); } else { body.parts(param.getPartName()); } } else { body.parts(""); } QName responseMessage = new QName(targetNamespace, method.getResponseMessageName()); generateSOAP12Headers(output, headerParams, responseMessage); } if (isRpc) { body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI()); } } for (CheckedExceptionImpl exception : method.getCheckedExceptions()) { Fault fault = operation.fault().name(exception.getMessageName()); extension.addBindingOperationFaultExtension(fault, method, exception); com.sun.xml.ws.wsdl.writer.document.soap12.SOAPFault soapFault = fault._element(com.sun.xml.ws.wsdl.writer.document.soap12.SOAPFault.class).name(exception.getMessageName()); soapFault.use(LITERAL); } } /** * * @param bodyParams * @param headerParams * @param params */ protected void splitParameters(List bodyParams, List headerParams, List params) { for (ParameterImpl parameter : params) { if (isBodyParameter(parameter)) { bodyParams.add(parameter); } else { headerParams.add(parameter); } } } /** * * @param writer * @param parameters * @param message */ protected void generateSOAPHeaders(TypedXmlWriter writer, List parameters, QName message) { for (ParameterImpl headerParam : parameters) { Header header = writer._element(Header.class); header.message(message); header.part(headerParam.getPartName()); header.use(LITERAL); } } /** * * @param writer * @param parameters * @param message */ protected void generateSOAP12Headers(TypedXmlWriter writer, List parameters, QName message) { for (ParameterImpl headerParam : parameters) { com.sun.xml.ws.wsdl.writer.document.soap12.Header header = writer._element(com.sun.xml.ws.wsdl.writer.document.soap12.Header.class); header.message(message); header.part(headerParam.getPartName()); header.use(LITERAL); } } /** * Generates the Service section of the WSDL */ protected void generateService() { QName portQName = model.getPortName(); QName serviceQName = model.getServiceQName(); Service service = serviceDefinitions.service().name(serviceQName.getLocalPart()); extension.addServiceExtension(service); Port port = service.port().name(portQName.getLocalPart()); port.binding(model.getBoundPortTypeName()); extension.addPortExtension(port); if (model.getJavaMethods().size() == 0) return; if(this.binding.getBindingId().getSOAPVersion()== SOAPVersion.SOAP_12){ com.sun.xml.ws.wsdl.writer.document.soap12.SOAPAddress address = port._element(com.sun.xml.ws.wsdl.writer.document.soap12.SOAPAddress.class); address.location(endpointAddress); }else{ SOAPAddress address = port._element(SOAPAddress.class); address.location(endpointAddress); } } /** * * @param operation * @param method */ protected void generateInputMessage(Operation operation, JavaMethodImpl method) { ParamType paramType = operation.input(); extension.addOperationInputExtension(paramType, method); // paramType.message(method.getOperation().getName()); paramType.message(new QName(model.getTargetNamespace(), method.getRequestMessageName())); } /** * * @param operation * @param method */ protected void generateOutputMessage(Operation operation, JavaMethodImpl method) { ParamType paramType = operation.output(); extension.addOperationOutputExtension(paramType, method); // paramType.message(new QName(model.getTargetNamespace(), method.getOperation().getLocalName()+RESPONSE)); paramType.message(new QName(model.getTargetNamespace(), method.getResponseMessageName())); } /** * Creates the {@link Result} object used by JAXB to generate a schema for the * namesapceUri namespace. * @param namespaceUri The namespace for the schema being generated * @param suggestedFileName the JAXB suggested file name for the schema file * @return the {@link Result} for JAXB to generate the schema into * @throws java.io.IOException thrown if on IO error occurs */ public Result createOutputFile(String namespaceUri, String suggestedFileName) throws IOException { Result result; if (namespaceUri.equals("")) { return null; } com.sun.xml.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import().namespace(namespaceUri); Holder fileNameHolder = new Holder (); fileNameHolder.value = schemaPrefix+suggestedFileName; result = wsdlResolver.getSchemaOutput(namespaceUri, fileNameHolder); // System.out.println("schema file: "+fileNameHolder.value); // System.out.println("result: "+result); String schemaLoc; if (result == null) schemaLoc = fileNameHolder.value; else schemaLoc = relativize(result.getSystemId(), wsdlLocation); // System.out.println("schemaLoca: "+schemaLoc); _import.schemaLocation(schemaLoc); return result; } /** * Relativizes a URI by using another URI (base URI.) * * * For example, {@code relative("http://www.sun.com/abc/def","http://www.sun.com/pqr/stu") => "../abc/def"} * *
* This method only works on hierarchical URI's, not opaque URI's (refer to the * java.net.URI * javadoc for complete definitions of these terms. * *
* This method will not normalize the relative URI. * @param uri the URI to relativize * * * @param baseUri the base URI to use for the relativization * @return the relative URI or the original URI if a relative one could not be computed */ protected static String relativize(String uri, String baseUri) { try { assert uri!=null; if(baseUri==null) return uri; URI theUri = new URI(escapeURI(uri)); URI theBaseUri = new URI(escapeURI(baseUri)); if (theUri.isOpaque() || theBaseUri.isOpaque()) return uri; if (!equalsIgnoreCase(theUri.getScheme(), theBaseUri.getScheme()) || !equal(theUri.getAuthority(), theBaseUri.getAuthority())) return uri; String uriPath = theUri.getPath(); String basePath = theBaseUri.getPath(); // normalize base path if (!basePath.endsWith("/")) { basePath = normalizeUriPath(basePath); } if( uriPath.equals(basePath)) return "."; String relPath = calculateRelativePath(uriPath, basePath); if (relPath == null) return uri; // recursion found no commonality in the two uris at all StringBuffer relUri = new StringBuffer(); relUri.append(relPath); if (theUri.getQuery() != null) relUri.append('?').append(theUri.getQuery()); if (theUri.getFragment() != null) relUri.append('#').append(theUri.getFragment()); return relUri.toString(); } catch (URISyntaxException e) { throw new InternalError("Error escaping one of these uris:\n\t"+uri+"\n\t"+baseUri); } } private static String calculateRelativePath(String uri, String base) { if (base == null) { return null; } if (uri.startsWith(base)) { return uri.substring(base.length()); } else { return "../" + calculateRelativePath(uri, getParentUriPath(base)); } } /** * Implements the SchemaOutputResolver used by JAXB to */ protected class JAXWSOutputSchemaResolver extends SchemaOutputResolver { /** * Creates the {@link Result} object used by JAXB to generate a schema for the * namesapceUri namespace. * @param namespaceUri The namespace for the schema being generated * @param suggestedFileName the JAXB suggested file name for the schema file * @return the {@link Result} for JAXB to generate the schema into * @throws java.io.IOException thrown if on IO error occurs */ public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { return createOutputFile(namespaceUri, suggestedFileName); } } private void register(WSDLGeneratorExtension h) { extensionHandlers.add(h); } }