blob: 045d0853f8387ead3b4a7c6f4335aacdbeb0222e [file] [log] [blame]
/*
* Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.xml.internal.ws.wsdl.writer;
import com.sun.xml.internal.ws.pept.presentation.MessageStruct;
import com.sun.xml.internal.bind.api.JAXBRIContext;
import static com.sun.xml.internal.bind.v2.schemagen.Util.*;
import com.sun.xml.internal.txw2.TXW;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import com.sun.xml.internal.txw2.output.ResultFactory;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import com.sun.xml.internal.ws.encoding.soap.SOAPVersion;
import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants;
import com.sun.xml.internal.ws.encoding.soap.streaming.SOAP12NamespaceConstants;
import com.sun.xml.internal.ws.model.CheckedException;
import com.sun.xml.internal.ws.model.JavaMethod;
import com.sun.xml.internal.ws.model.Parameter;
import com.sun.xml.internal.ws.model.ParameterBinding;
import com.sun.xml.internal.ws.model.RuntimeModel;
import com.sun.xml.internal.ws.model.WrapperParameter;
import com.sun.xml.internal.ws.model.soap.SOAPBinding;
import com.sun.xml.internal.ws.model.soap.Style;
import com.sun.xml.internal.ws.model.soap.Use;
import com.sun.xml.internal.ws.wsdl.parser.SOAPConstants;
import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants;
import com.sun.xml.internal.ws.wsdl.writer.document.Binding;
import com.sun.xml.internal.ws.wsdl.writer.document.BindingOperationType;
import com.sun.xml.internal.ws.wsdl.writer.document.Definitions;
import com.sun.xml.internal.ws.wsdl.writer.document.Fault;
import com.sun.xml.internal.ws.wsdl.writer.document.FaultType;
import com.sun.xml.internal.ws.wsdl.writer.document.Import;
import com.sun.xml.internal.ws.wsdl.writer.document.Message;
import com.sun.xml.internal.ws.wsdl.writer.document.Operation;
import com.sun.xml.internal.ws.wsdl.writer.document.ParamType;
import com.sun.xml.internal.ws.wsdl.writer.document.Port;
import com.sun.xml.internal.ws.wsdl.writer.document.PortType;
import com.sun.xml.internal.ws.wsdl.writer.document.Service;
import com.sun.xml.internal.ws.wsdl.writer.document.Types;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.Body;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.BodyType;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.Header;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPAddress;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPFault;
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 <code>RunTimeModel</code>
*
* @author WS Development Team
*/
public class WSDLGenerator {
private JAXWSOutputSchemaResolver resolver;
private WSDLOutputResolver wsdlResolver = null;
private RuntimeModel model;
private Definitions serviceDefinitions;
private Definitions portDefinitions;
private Types types;
public static final String DOT_WSDL = ".wsdl";
public static final String RESPONSE = "Response";
public static final String PARAMETERS = "parameters";
public static final String RESULT = "parameters";
public static final String UNWRAPPABLE_RESULT = "result";
public static final String WSDL_NAMESPACE = WSDLConstants.NS_WSDL;
public static final String WSDL_PREFIX = "wsdl";
public static final String XSD_NAMESPACE = SOAPNamespaceConstants.XSD;
public static final String XSD_PREFIX = "xsd";
public static final String SOAP11_NAMESPACE = SOAPConstants.NS_WSDL_SOAP;
public static final String SOAP12_NAMESPACE = SOAPConstants.NS_WSDL_SOAP12;
public static final String SOAP_PREFIX = "soap";
public static final String SOAP12_PREFIX = "soap12";
public static final String TNS_PREFIX = "tns";
public static final String BINDING = "Binding";
public static final String SOAP_HTTP_TRANSPORT = SOAPNamespaceConstants.TRANSPORT_HTTP;
public static final String SOAP12_HTTP_TRANSPORT = SOAP12NamespaceConstants.TRANSPORT_HTTP;
public static final String DOCUMENT = "document";
public static final String RPC = "rpc";
public static final String LITERAL = "literal";
public static final String REPLACE_WITH_ACTUAL_URL = "REPLACE_WITH_ACTUAL_URL";
private Set<QName> processedExceptions = new HashSet<QName>();
private String bindingId;
private String wsdlLocation;
private String portWSDLID;
private String schemaPrefix;
public WSDLGenerator(RuntimeModel model, WSDLOutputResolver wsdlResolver, String bindingId) {
this.model = model;
resolver = new JAXWSOutputSchemaResolver();
this.wsdlResolver = wsdlResolver;
this.bindingId = bindingId;
}
public void doGeneration() {
XmlSerializer serviceWriter;
XmlSerializer portWriter = null;
String fileName = JAXBRIContext.mangleNameToClassName(model.getServiceQName().getLocalPart());
// System.out.println("concrete name: "+ fileName);
Result result = wsdlResolver.getWSDLOutput(fileName+DOT_WSDL);
if (result == null)
return;
wsdlLocation = result.getSystemId();
serviceWriter = 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";
// System.out.println("abstract name: "+ wsdlName);
Holder<String> absWSDLName = new Holder<String>();
absWSDLName.value = wsdlName+DOT_WSDL;
// System.out.println("absWSDLName.value: "+ absWSDLName.value);
result = wsdlResolver.getAbstractWSDLOutput(absWSDLName);
// System.out.println("absWSDLName.value: "+ absWSDLName.value);
// schemaPrefix = model.getJAXBContext().mangleNameToClassName(portWSDLID)+"_";
if (result != null) {
portWSDLID = result.getSystemId();
if (portWSDLID.equals(wsdlLocation)) {
portWriter = serviceWriter;
} else {
portWriter = 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)+"_";
// System.out.println("portWSDLID: "+ portWSDLID);
// schemaPrefix = model.getJAXBContext().mangleNameToClassName(portWSDLID)+"_";
// System.out.println("schemaPrefix: "+ schemaPrefix);
}
generateDocument(serviceWriter, portWriter);
}
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(bindingId.equals(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING))
serviceDefinitions._namespace(SOAP12_NAMESPACE, SOAP12_PREFIX);
else
serviceDefinitions._namespace(SOAP11_NAMESPACE, SOAP_PREFIX);
serviceDefinitions.name(model.getServiceQName().getLocalPart());
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);
}
if (portDefinitions != null) {
generateTypes();
generateMessages();
generatePortType();
}
generateBinding();
generateService();
serviceDefinitions.commit();
if (portDefinitions != null && portDefinitions != serviceDefinitions)
portDefinitions.commit();
}
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());
}
}
}
protected void generateMessages() {
for (JavaMethod method : model.getJavaMethods()) {
if (method.getBinding() instanceof SOAPBinding)
generateSOAPMessages(method, (SOAPBinding)method.getBinding());
}
}
protected void generateSOAPMessages(JavaMethod method, SOAPBinding binding) {
boolean isDoclit = binding.isDocLit();
Message message = portDefinitions.message().name(method.getOperationName());
com.sun.xml.internal.ws.wsdl.writer.document.Part part;
JAXBRIContext jaxbContext = model.getJAXBContext();
boolean unwrappable = true;
for (Parameter 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 (Parameter childParam : ((WrapperParameter)param).getWrapperChildren()) {
part = message.part().name(childParam.getPartName());
part.type(jaxbContext.getTypeName(childParam.getTypeReference()));
}
} else {
part = message.part().name(param.getPartName());
part.element(param.getName());
}
}
}
if (method.getMEP() != MessageStruct.ONE_WAY_MEP) {
message = portDefinitions.message().name(method.getOperationName()+RESPONSE);
if (unwrappable) {
for (Parameter param : method.getResponseParameters()) {
if (isHeaderParameter(param))
unwrappable = false;
}
}
for (Parameter 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 (Parameter childParam : ((WrapperParameter)param).getWrapperChildren()) {
part = message.part().name(childParam.getPartName());
part.type(jaxbContext.getTypeName(childParam.getTypeReference()));
}
} else {
part = message.part().name(param.getPartName());
part.element(param.getName());
}
}
}
}
for (CheckedException exception : method.getCheckedExceptions()) {
QName tagName = exception.getDetailType().tagName;
// if (processedExceptions.contains(tagName))
// continue;
// message = portDefinitions.message().name(tagName.getLocalPart());
String messageName = exception.getMessageName();
QName messageQName = new QName(model.getTargetNamespace(), messageName);
if (processedExceptions.contains(messageQName))
continue;
message = portDefinitions.message().name(messageName);
part = message.part().name("fault");//tagName.getLocalPart());
part.element(tagName);
// processedExceptions.add(tagName);
processedExceptions.add(messageQName);
}
}
protected void generatePortType() {
PortType portType = portDefinitions.portType().name(model.getPortTypeName().getLocalPart());
for (JavaMethod method : model.getJavaMethods()) {
Operation operation = portType.operation().name(method.getOperationName());
generateParameterOrder(operation, method);
switch (method.getMEP()) {
case MessageStruct.REQUEST_RESPONSE_MEP:
// input message
generateInputMessage(operation, method);
// output message
generateOutputMessage(operation, method);
break;
case MessageStruct.ONE_WAY_MEP:
generateInputMessage(operation, method);
break;
}
// faults
for (CheckedException exception : method.getCheckedExceptions()) {
QName tagName = exception.getDetailType().tagName;
// QName messageName = new QName(model.getTargetNamespace(), tagName.getLocalPart());
// FaultType paramType = operation.fault().name(tagName.getLocalPart()).message(messageName);
QName messageName = new QName(model.getTargetNamespace(), exception.getMessageName());
FaultType paramType = operation.fault().name(exception.getMessageName()).message(messageName);
}
}
}
protected boolean isWrapperStyle(JavaMethod method) {
if (method.getRequestParameters().size() > 0) {
Parameter param = method.getRequestParameters().iterator().next();
return param.isWrapperStyle();
}
return false;
}
protected boolean isRpcLit(JavaMethod method) {
if (method.getBinding() instanceof SOAPBinding) {
if (((SOAPBinding)method.getBinding()).getStyle().equals(Style.RPC))
return true;
}
return false;
}
protected void generateParameterOrder(Operation operation, JavaMethod method) {
if (method.getMEP() == MessageStruct.ONE_WAY_MEP)
return;
if (isRpcLit(method))
generateRpcParameterOrder(operation, method);
else
generateDocumentParameterOrder(operation, method);
}
protected void generateRpcParameterOrder(Operation operation, JavaMethod method) {
String partName;
StringBuffer paramOrder = new StringBuffer();
Set<String> partNames = new HashSet<String>();
List<Parameter> sortedParams = sortMethodParameters(method);
int i = 0;
for (Parameter parameter : sortedParams) {
if (parameter.getIndex() >= 0) {
partName = parameter.getPartName();
if (!partNames.contains(partName)) {
if (i++ > 0)
paramOrder.append(' ');
paramOrder.append(partName);
partNames.add(partName);
}
}
}
operation.parameterOrder(paramOrder.toString());
}
protected void generateDocumentParameterOrder(Operation operation, JavaMethod method) {
String partName;
StringBuffer paramOrder = new StringBuffer();
Set<String> partNames = new HashSet<String>();
List<Parameter> sortedParams = sortMethodParameters(method);
boolean isWrapperStyle = isWrapperStyle(method);
int i = 0;
for (Parameter 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());
}
}
protected List<Parameter> sortMethodParameters(JavaMethod method) {
Set<Parameter> paramSet = new HashSet<Parameter>();
List<Parameter> sortedParams = new ArrayList<Parameter>();
if (isRpcLit(method)) {
for (Parameter param : method.getRequestParameters()) {
if (param instanceof WrapperParameter) {
paramSet.addAll(((WrapperParameter)param).getWrapperChildren());
} else {
paramSet.add(param);
}
}
for (Parameter 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<Parameter>params = paramSet.iterator();
if (paramSet.size() == 0)
return sortedParams;
Parameter param = params.next();
sortedParams.add(param);
Parameter sortedParam;
int pos;
for (int i=1; i<paramSet.size();i++) {
param = params.next();
for (pos=0; pos<i; pos++) {
sortedParam = sortedParams.get(pos);
if (param.getIndex() == sortedParam.getIndex() &&
param instanceof WrapperParameter)
break;
if (param.getIndex() < sortedParam.getIndex()) {
break;
}
}
sortedParams.add(pos, param);
}
return sortedParams;
}
protected boolean isBodyParameter(Parameter parameter) {
ParameterBinding paramBinding = parameter.getBinding();
return paramBinding.isBody();
}
protected boolean isHeaderParameter(Parameter parameter) {
ParameterBinding paramBinding = parameter.getBinding();
return paramBinding.isHeader();
}
protected boolean isAttachmentParameter(Parameter parameter) {
ParameterBinding paramBinding = parameter.getBinding();
return paramBinding.isAttachment();
}
protected void generateBinding() {
Binding binding = serviceDefinitions.binding().name(model.getPortName().getLocalPart()+BINDING);
binding.type(model.getPortTypeName());
boolean first = true;
for (JavaMethod method : model.getJavaMethods()) {
if (first) {
if (method.getBinding() instanceof SOAPBinding) {
SOAPBinding sBinding = (SOAPBinding)method.getBinding();
SOAPVersion soapVersion = sBinding.getSOAPVersion();
if(soapVersion.equals(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)){
com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPBinding soapBinding = binding.soap12Binding();
soapBinding.transport(SOAP12_HTTP_TRANSPORT);
if (sBinding.getStyle().equals(Style.DOCUMENT))
soapBinding.style(DOCUMENT);
else
soapBinding.style(RPC);
}else{
com.sun.xml.internal.ws.wsdl.writer.document.soap.SOAPBinding soapBinding = binding.soapBinding();
soapBinding.transport(SOAP_HTTP_TRANSPORT);
if (sBinding.getStyle().equals(Style.DOCUMENT))
soapBinding.style(DOCUMENT);
else
soapBinding.style(RPC);
}
}
first = false;
}
if(bindingId.equals(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING))
generateSOAP12BindingOperation(method, binding);
else
generateBindingOperation(method, binding);
}
}
protected void generateBindingOperation(JavaMethod method, Binding binding) {
BindingOperationType operation = binding.operation().name(method.getOperationName());
String targetNamespace = model.getTargetNamespace();
QName requestMessage = new QName(targetNamespace, method.getOperationName());
QName responseMessage = new QName(targetNamespace, method.getOperationName()+RESPONSE);
if (method.getBinding() instanceof SOAPBinding) {
List<Parameter> bodyParams = new ArrayList<Parameter>();
List<Parameter> headerParams = new ArrayList<Parameter>();
splitParameters(bodyParams, headerParams, method.getRequestParameters());
SOAPBinding soapBinding = (SOAPBinding)method.getBinding();
operation.soapOperation().soapAction(soapBinding.getSOAPAction());
// input
TypedXmlWriter input = operation.input();
BodyType body = input._element(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) {
Parameter param = bodyParams.iterator().next();
if (isRpc) {
StringBuffer parts = new StringBuffer();
int i=0;
for (Parameter 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() != MessageStruct.ONE_WAY_MEP) {
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();
body = output._element(Body.class);
body.use(LITERAL);
if (headerParams.size() > 0) {
String parts = "";
if (bodyParams.size() > 0) {
Parameter param = bodyParams.iterator().next();
if (isRpc) {
int i=0;
for (Parameter parameter : ((WrapperParameter)param).getWrapperChildren()) {
if (i++>0)
parts += " ";
parts += parameter.getPartName();
}
} else {
if (param != null) {
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);
generateSOAPHeaders(output, headerParams, responseMessage);
}
if (isRpc) {
body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI());
}
}
for (CheckedException exception : method.getCheckedExceptions()) {
// QName tagName = exception.getDetailType().tagName;
// Fault fault = operation.fault().name(tagName.getLocalPart());
// SOAPFault soapFault = fault._element(SOAPFault.class).name(tagName.getLocalPart());
Fault fault = operation.fault().name(exception.getMessageName());
SOAPFault soapFault = fault._element(SOAPFault.class).name(exception.getMessageName());
soapFault.use(LITERAL);
}
}
}
protected void generateSOAP12BindingOperation(JavaMethod method, Binding binding) {
BindingOperationType operation = binding.operation().name(method.getOperationName());
String targetNamespace = model.getTargetNamespace();
QName requestMessage = new QName(targetNamespace, method.getOperationName());
QName responseMessage = new QName(targetNamespace, method.getOperationName()+RESPONSE);
if (method.getBinding() instanceof SOAPBinding) {
List<Parameter> bodyParams = new ArrayList<Parameter>();
List<Parameter> headerParams = new ArrayList<Parameter>();
splitParameters(bodyParams, headerParams, method.getRequestParameters());
SOAPBinding soapBinding = (SOAPBinding)method.getBinding();
operation.soap12Operation().soapAction(soapBinding.getSOAPAction());
// input
TypedXmlWriter input = operation.input();
com.sun.xml.internal.ws.wsdl.writer.document.soap12.BodyType body = input._element(com.sun.xml.internal.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) {
Parameter param = bodyParams.iterator().next();
if (isRpc) {
StringBuffer parts = new StringBuffer();
int i=0;
for (Parameter 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() != MessageStruct.ONE_WAY_MEP) {
// 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();
body = output._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Body.class);
body.use(LITERAL);
if (headerParams.size() > 0) {
if (bodyParams.size() > 0) {
Parameter param = bodyParams.iterator().next();
if (isRpc) {
String parts = "";
int i=0;
for (Parameter 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("");
}
generateSOAP12Headers(output, headerParams, responseMessage);
}
if (isRpc) {
body.namespace(method.getRequestParameters().iterator().next().getName().getNamespaceURI());
}
}
for (CheckedException exception : method.getCheckedExceptions()) {
// QName tagName = exception.getDetailType().tagName;
// Fault fault = operation.fault().name(tagName.getLocalPart());
// 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(tagName.getLocalPart());
Fault fault = operation.fault().name(exception.getMessageName());
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());
soapFault.use(LITERAL);
}
}
}
protected void splitParameters(List<Parameter> bodyParams, List<Parameter>headerParams, List<Parameter>params) {
for (Parameter parameter : params) {
if (isBodyParameter(parameter)) {
bodyParams.add(parameter);
} else {
headerParams.add(parameter);
}
}
}
protected void generateSOAPHeaders(TypedXmlWriter writer, List<Parameter> parameters, QName message) {
for (Parameter headerParam : parameters) {
Header header = writer._element(Header.class);
header.message(message);
header.part(headerParam.getPartName());
header.use(LITERAL);
}
}
protected void generateSOAP12Headers(TypedXmlWriter writer, List<Parameter> parameters, QName message) {
for (Parameter headerParam : parameters) {
com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header header = writer._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.Header.class);
header.message(message);
header.part(headerParam.getPartName());
header.use(LITERAL);
}
}
protected void generateService() {
QName portQName = model.getPortName();
QName serviceQName = model.getServiceQName();
Service service = serviceDefinitions.service().name(serviceQName.getLocalPart());
Port port = service.port().name(portQName.getLocalPart());
port.binding(new QName(serviceQName.getNamespaceURI(), portQName.getLocalPart()+BINDING));
if (model.getJavaMethods().size() == 0)
return;
if (model.getJavaMethods().iterator().next().getBinding() instanceof SOAPBinding) {
if(bindingId.equals(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)){
com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress address = port._element(com.sun.xml.internal.ws.wsdl.writer.document.soap12.SOAPAddress.class);
address.location(REPLACE_WITH_ACTUAL_URL);
}else{
SOAPAddress address = port._element(SOAPAddress.class);
address.location(REPLACE_WITH_ACTUAL_URL);
}
}
}
protected void generateInputMessage(Operation operation, JavaMethod method) {
ParamType paramType = operation.input();
paramType.message(new QName(model.getTargetNamespace(), method.getOperationName()));
}
protected void generateOutputMessage(Operation operation, JavaMethod method) {
ParamType paramType = operation.output();
paramType.message(new QName(model.getTargetNamespace(), method.getOperationName()+RESPONSE));
}
public Result createOutputFile(String namespaceUri, String suggestedFileName) throws IOException {
Result result;
if (namespaceUri.equals("")) {
return null;
}
com.sun.xml.internal.ws.wsdl.writer.document.xsd.Import _import = types.schema()._import().namespace(namespaceUri);
Holder<String> fileNameHolder = new Holder<String>();
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.)
*
* <p>
* For example, {@code relative("http://www.sun.com/abc/def","http://www.sun.com/pqr/stu") => "../abc/def"}
*
* <p>
* This method only works on hierarchical URI's, not opaque URI's (refer to the
* <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/URI.html">java.net.URI</a>
* javadoc for complete definitions of these terms.
*
* <p>
* This method will not normalize the relative URI.
*
* @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));
}
}
protected class JAXWSOutputSchemaResolver extends SchemaOutputResolver {
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
return createOutputFile(namespaceUri, suggestedFileName);
}
}
}