blob: 061fbbf6f8369efe32f8c5342e209b670fc38d80 [file] [log] [blame]
package org.apache.axis2.description;
import com.ibm.wsdl.util.xml.DOM2Writer;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.wsdl.WSDL11ActionHelper;
import org.apache.axis2.util.PolicyUtil;
import org.apache.axis2.util.XMLUtils;
import org.apache.axis2.wsdl.SOAPHeaderMessage;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Constants;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyReference;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.wsdl.*;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.extensions.soap.*;
import javax.wsdl.extensions.soap12.*;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLLocator;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*
*/
public class WSDL11ToAxisServiceBuilder extends WSDLToAxisServiceBuilder {
protected static final Log log = LogFactory
.getLog(WSDL11ToAxisServiceBuilder.class);
protected String portName;
private static final String BINDING = "Binding";
private static final String SERVICE = "Service";
private static final String PORT = "Port";
private static final String PORT_TYPE = "PortType";
private static final String PORT_TYPE_OPERATION = "PortType.Operation";
private static final String PORT_TYPE_OPERATION_INPUT = "PortType.Operation.Input";
private static final String PORT_TYPE_OPERATION_OUTPUT = "PortType.Operation.Output";
private static final String PORT_TYPE_OPERATION_FAULT = "PortType.Operation.Fault";
private static final String BINDING_OPERATION = "Binding.Operation";
private static final String BINDING_OPERATION_INPUT = "Binding.Operation.Input";
private static final String BINDING_OPERATION_OUTPUT = "Binding.Operation.Output";
protected Definition wsdl4jDefinition = null;
private WSDLLocator customWSLD4JResolver;
public static final String RPC_STYLE = "rpc";
public static final String DOCUMENT_STYLE = "document";
/**
* Keeps a list of processable operations initiate to an empty list
*/
private List wrappableOperations = new ArrayList();
public static final String WRAPPED_OUTPUTNAME_SUFFIX = "Response";
public static final String XML_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";
public static final String NAMESPACE_DECLARATION_PREFIX = "xmlns:";
private static int prefixCounter = 0;
public static final String NAMESPACE_URI = "namespace";
public static final String TRAGET_NAMESPACE = "targetNamespace";
/**
* keep track of whether setup code related to the entire wsdl is complete.
* Note that WSDL11ToAllAxisServices will call setup multiple times, so this
* field is used to make subsequent calls no-ops.
*/
private boolean setupComplete = false;
private Map schemaMap = null;
private static final String JAVAX_WSDL_VERBOSE_MODE_KEY = "javax.wsdl.verbose";
private static final String JAVAX_WSDL_IMPORT_DOCUMENTS_MODE_KEY = "javax.wsdl.importDocuments";
/**
* constructor taking in the service name and the port name
*
* @param in
* @param serviceName
* @param portName
*/
public WSDL11ToAxisServiceBuilder(InputStream in, QName serviceName,
String portName) {
super(in, serviceName);
this.portName = portName;
}
/**
* @param def
* @param serviceName
* @param portName
*/
public WSDL11ToAxisServiceBuilder(Definition def, QName serviceName,
String portName) {
super(null, serviceName);
this.wsdl4jDefinition = def;
this.portName = portName;
}
/**
* @param in
* @param service
*/
public WSDL11ToAxisServiceBuilder(InputStream in, AxisService service) {
super(in, service);
}
/**
* @param in
*/
public WSDL11ToAxisServiceBuilder(InputStream in) {
this(in, null, null);
}
/**
* sets a custem WSDL4J locator
*
* @param customWSLD4JResolver
*/
public void setCustomWSLD4JResolver(WSDLLocator customWSLD4JResolver) {
this.customWSLD4JResolver = customWSLD4JResolver;
}
/**
* populates a given service This is the only publicly accessible method in
* this class
*
* @throws AxisFault
*/
public AxisService populateService() throws AxisFault {
try {
setup();
// Setting wsdl4jdefintion to axisService , so if some one want
// to play with it he can do that by getting the parameter
Parameter wsdlDefinitionParameter = new Parameter();
wsdlDefinitionParameter.setName(WSDLConstants.WSDL_4_J_DEFINITION);
wsdlDefinitionParameter.setValue(wsdl4jDefinition);
axisService.addParameter(wsdlDefinitionParameter);
if (wsdl4jDefinition == null) {
return null;
}
// setting target name space
axisService.setTargetNamespace(wsdl4jDefinition
.getTargetNamespace());
axisService.setNameSpacesMap(new NamespaceMap(wsdl4jDefinition
.getNamespaces()));
Binding binding = findBinding(wsdl4jDefinition);
if (binding.getPortType() == null) {
throw new AxisFault("Unable to find wsdl:binding named " + binding.getQName());
}
// create new Schema extensions element for wrapping
// (if its present)
Element[] schemaElements = generateWrapperSchema(schemaMap, binding);
// we might have modified the schemas by now so the addition should
// happen here
Types wsdl4jTypes = wsdl4jDefinition.getTypes();
if (null != wsdl4jTypes) {
this.copyExtensibleElements(wsdl4jTypes
.getExtensibilityElements(), wsdl4jDefinition,
axisService, TYPES);
}
// add the newly created schemas
if (schemaElements != null && schemaElements.length > 0) {
for (int i = 0; i < schemaElements.length; i++) {
Element schemaElement = schemaElements[i];
if (schemaElement != null) {
axisService
.addSchema(getXMLSchema(schemaElement, null));
}
}
}
// copy the documentation element content to the description
Element documentationElement = wsdl4jDefinition
.getDocumentationElement();
if (documentationElement != null) {
Node firstChild = documentationElement.getFirstChild();
String serviceDes;
if (firstChild.getNodeType() == Node.TEXT_NODE) {
serviceDes = firstChild.getNodeValue();
} else {
serviceDes = DOM2Writer.nodeToString(firstChild);
}
axisService.setServiceDescription(serviceDes);
}
processBinding(binding, wsdl4jDefinition);
return axisService;
} catch (WSDLException e) {
log.error(e);
throw new AxisFault(e);
} catch (Exception e) {
log.error(e);
throw new AxisFault(e);
}
}
/**
* contains all code which gathers non-service specific information from the
* wsdl. <p/> After all the setup completes successfully, the setupComplete
* field is set so that any subsequent calls to setup() will result in a
* no-op. Note that subclass WSDL11ToAllAxisServicesBuilder will call
* populateService for each port in the WSDL. Separating the non-service
* specific information here allows WSDL11ToAllAxisServicesBuilder to only
* do this work 1 time per WSDL, instead of for each port on each service.
*
* @throws WSDLException if readInTheWSDLFile fails
*/
protected void setup() throws WSDLException {
if (setupComplete) { // already setup, just do nothing and return
return;
}
if (wsdl4jDefinition == null) {
wsdl4jDefinition = readInTheWSDLFile(in);
}
if (wsdl4jDefinition == null) {
return; // can't continue without wsdl
}
// process the imports
// send an empty list as the processed namespace list since this
// is the first call
processImports(wsdl4jDefinition, new ArrayList());
// Adding the policies in the Definition to the the PolicyRegistry
processPoliciesInDefintion(wsdl4jDefinition);
// setup the schemaMap
schemaMap = populateSchemaMap(wsdl4jDefinition.getTypes());
setupComplete = true; // if any part of setup fails, don't mark
// setupComplete
}
/**
* Populate a map of targetNamespace vs DOM schema element This is used to
* grab the correct schema element when adding a new element
*
* @param wsdl4jTypes
*/
private Map populateSchemaMap(Types wsdl4jTypes) {
Map schemaMap = new HashMap();
if (wsdl4jTypes != null) {
List typesExtensibilityElements = wsdl4jTypes
.getExtensibilityElements();
for (int i = 0; i < typesExtensibilityElements.size(); i++) {
Object o = typesExtensibilityElements.get(i);
if (o instanceof Schema) {
Schema s = (Schema) o;
String targetNamespace = s.getElement().getAttribute(
TRAGET_NAMESPACE);
schemaMap.put(targetNamespace, s.getElement());
}
}
}
return schemaMap;
}
/**
* Look for the relevant binding!
*
* @param dif
* @throws AxisFault
*/
private Binding findBinding(Definition dif) throws AxisFault {
Map services = dif.getServices();
Service service = null;
Binding binding = null;
Port port = null;
if (serviceName != null) {
service = (Service) services.get(serviceName);
if (service == null) {
throw new AxisFault("Service " + serviceName + " was not found in the WSDL");
}
} else {
if (services.size() > 0) {
// pick the first service - we don't really have a choice here
service = (Service) services.values().toArray()[0];
}
}
if (service != null) {
copyExtensibleElements(service.getExtensibilityElements(), dif,
axisService, SERVICE);
if (portName != null) {
port = service.getPort(portName);
if (port == null) {
throw new AxisFault("No port found for the given name :"
+ portName);
}
} else {
Map ports = service.getPorts();
if (ports != null && ports.size() > 0) {
// pick the port with the SOAP address as the default port
port = findSOAPPort(ports);
if (port == null) {
// a SOAP port was not found - log a warning
// and use the first port in the list
log.info("A SOAP port was not found - "
+ "picking a random port!");
port = (Port) ports.values().toArray()[0];
}
}
}
axisService.setName(service.getQName().getLocalPart());
if (port != null) {
copyExtensibleElements(port.getExtensibilityElements(), dif,
axisService, PORT);
binding = dif.getBinding(port.getBinding().getQName());
if (binding == null) {
binding = port.getBinding();
}
}
} else {
log.info("A service element was not found - "
+ "picking a random binding!");
Collection bindings = dif.getBindings().values();
if (bindings == null || bindings.isEmpty()) {
throw new AxisFault("No bindings found in wsdl");
}
binding = (Binding) bindings.iterator().next();
axisService.setName(binding.getQName().getLocalPart() + "Service");
}
return binding;
}
/**
* Finds a SOAP port given the port map
*
* @param ports
*/
private Port findSOAPPort(Map ports) {
Port port;
for (Iterator portsIterator = ports.values().iterator(); portsIterator
.hasNext();) {
port = (Port) portsIterator.next();
List extensibilityElements = port.getExtensibilityElements();
for (int i = 0; i < extensibilityElements.size(); i++) {
Object extElement = extensibilityElements.get(i);
if (extElement instanceof SOAPAddress) {
// SOAP 1.1 address found - return that port and we are done
return port;
}
if (extElement instanceof SOAP12Address) {
// SOAP 1.2 address found - return that port and we are done
return port;
}
}
}
// None found - just return null.
return null;
}
/**
* Process the binding
*
* @param binding
* @param dif
* @throws Exception
*/
private void processBinding(Binding binding, Definition dif)
throws Exception {
if (binding != null) {
copyExtensibleElements(binding.getExtensibilityElements(), dif,
axisService, BINDING);
PortType portType = dif.getPortType(binding.getPortType().getQName());
processPortType(portType, dif);
axisService.setBindingName(binding.getQName().getLocalPart());
// String portTypeNs = portType.getQName().getNamespaceURI();
List list = binding.getBindingOperations();
for (int i = 0; i < list.size(); i++) {
BindingOperation wsdl4jBindingOperation = (BindingOperation) list
.get(i);
AxisOperation operation = axisService.getOperation(new QName(
wsdl4jBindingOperation.getName()));
// this should first check the style of the binding
// and then set the style in the axis operation
// if that is not present, then only the global style applies
// this style is either rpc or doc
String style = getSOAPStyle(wsdl4jBindingOperation);
if (style != null) {
operation.setStyle(style);
} else if (this.style != null) {
operation.setStyle(this.style);
}
copyExtensibleElements(wsdl4jBindingOperation
.getExtensibilityElements(), dif, operation,
BINDING_OPERATION);
BindingInput bindingInput = wsdl4jBindingOperation
.getBindingInput();
BindingOutput bindingOutput = wsdl4jBindingOperation
.getBindingOutput();
Map bindingFaultsMap = wsdl4jBindingOperation
.getBindingFaults();
Operation wsdl4jOperation = findOperation(portType, wsdl4jBindingOperation);
String MEP = operation.getMessageExchangePattern();
/* Process the binding inputs */
if (bindingInput != null) {
if (WSDLUtil.isInputPresentForMEP(MEP)) {
AxisMessage inAxisMessage = operation
.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
// Add the Qname reference - this has to be done by
// looking at the
// binding
AddQNameReference(inAxisMessage, wsdl4jOperation,
bindingInput, wrappableOperations
.contains(wsdl4jBindingOperation
.getOperation()));
copyExtensibleElements(bindingInput
.getExtensibilityElements(), dif,
inAxisMessage, BINDING_OPERATION_INPUT);
}
}
/*
* Process the binding outputs
*/
if (bindingOutput != null) {
if (WSDLUtil.isOutputPresentForMEP(MEP)) {
AxisMessage outAxisMessage = operation
.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
// Add the Qname reference - this has to be done by
// looking at the
// binding
AddQNameReference(outAxisMessage, wsdl4jOperation,
bindingOutput, wrappableOperations
.contains(wsdl4jBindingOperation
.getOperation()));
copyExtensibleElements(bindingOutput
.getExtensibilityElements(), dif,
outAxisMessage, BINDING_OPERATION_OUTPUT);
}
}
/* process the binding faults */
for (Iterator faultKeys = bindingFaultsMap.keySet().iterator(); faultKeys
.hasNext();) {
Object faultMapKey = faultKeys.next();
BindingFault bindingFault = (BindingFault) bindingFaultsMap
.get(faultMapKey);
Fault wsdl4jFault = wsdl4jOperation.getFault(bindingFault
.getName());
if (wsdl4jFault == null || wsdl4jFault.getMessage().getParts().size() == 0) {
throw new AxisFault("fault \"" + bindingFault.getName()
+ "\" not found in the Operation "
+ wsdl4jOperation.getName());
}
AxisMessage faultMessage = findFaultMessage(wsdl4jFault
.getMessage().getQName().getLocalPart(), operation
.getFaultMessages());
AddQNameReference(faultMessage, wsdl4jFault.getMessage());
}
Iterator iterator = operation.getFaultMessages().iterator();
while (iterator.hasNext()) {
AxisMessage faultMessage = (AxisMessage) iterator.next();
if (faultMessage.getElementQName() == null) {
log.warn("Unable to find a wsdl:binding/wsdl:operation/wsdl:fault for fault named " + faultMessage.getName() + " defined in wsdl:portType/wsdl:operation/@name=" + operation.getName().getLocalPart());
}
}
}
}
}
private Operation findOperation(PortType portType, BindingOperation wsdl4jBindingOperation) {
Operation op = wsdl4jBindingOperation
.getOperation();
String input = null;
if (op != null && op.getInput() != null) {
input = op.getInput().getName();
if (":none".equals(input)) {
input = null;
}
}
String output = null;
if (op != null && op.getOutput() != null) {
output = op.getOutput().getName();
if (":none".equals(output)) {
output = null;
}
}
Operation op2 = portType.getOperation(op.getName(), input, output);
return ((op2 == null) ? op : op2);
}
/**
* Find the fault message relevant to a given name from the fault message
* list
*
* @param name
* @param faultMessages
*/
private AxisMessage findFaultMessage(String name, ArrayList faultMessages) {
AxisMessage tempMessage;
for (int i = 0; i < faultMessages.size(); i++) {
tempMessage = (AxisMessage) faultMessages.get(i);
if (name.equals(tempMessage.getName())) {
return tempMessage;
}
}
return null;
}
/**
* Add the QName for the binding input
*
* @param inMessage
* @param wsdl4jOperation
* @param bindingInput
* @param isWrapped
*/
private void AddQNameReference(AxisMessage inMessage,
Operation wsdl4jOperation, BindingInput bindingInput,
boolean isWrapped) {
List extensibilityElements = bindingInput.getExtensibilityElements();
Message wsdl4jMessage = wsdl4jOperation.getInput().getMessage();
for (int i = 0; i < extensibilityElements.size(); i++) {
ExtensibilityElement extElement = (ExtensibilityElement) extensibilityElements
.get(i);
// SOAP 1.1 body element found!
if (extElement instanceof SOAPBody) {
SOAPBody soapBody = (SOAPBody) extElement;
List bindingPartsList = soapBody.getParts();
if (bindingPartsList != null && !bindingPartsList.isEmpty()) {
// we can process a single part only
processPartsList(bindingPartsList, wsdl4jMessage, inMessage);
// there are no parts named in the binding - process the
// items normally
// by looking at the single message part - or the wrapped
// items if wrapped by us
} else {
// for the wrapped types we need to find this from the
// wrapper schema map
if (isWrapped) {
// The schema for this should be already made ! Find the
// QName from
// the list and add it - the name for this is just the
inMessage
.setElementQName((QName) resolvedRpcWrappedElementMap
.get(wsdl4jOperation.getName()));
} else if (wsdl4jMessage != null) {
// pick the first part from the list and take that as
// the relevant part
// it is somewhat questionnable whether the first part
// gets picked
// but we'll have to take a chance here
Map wsdl4jPartsMap = wsdl4jMessage.getParts();
if (!wsdl4jPartsMap.isEmpty()) {
Part wsdl4jPart = (Part) wsdl4jPartsMap.values()
.toArray()[0];
if (wsdl4jPart.getElementName() != null) {
inMessage.setElementQName(wsdl4jPart
.getElementName());
}
}
}
}
break;
} else if (extElement instanceof SOAP12Body) {
SOAP12Body soapBody = (SOAP12Body) extElement;
List bindingPartsList = soapBody.getParts();
if (bindingPartsList != null && !bindingPartsList.isEmpty()) {
// we can process a single part only
processPartsList(bindingPartsList, wsdl4jMessage, inMessage);
// there are no parts named in the binding - process the
// items normally
// by looking at the single message part - or the wrapped
// items if wrapped by us
} else {
// for the wrapped types we need to find this from the
// wrapper schema map
if (isWrapped) {
// The schema for this should be already made ! Find the
// QName from
// the list and add it - the name for this is just the
inMessage
.setElementQName((QName) resolvedRpcWrappedElementMap
.get(wsdl4jOperation.getName()));
} else if (wsdl4jMessage != null) {
// pick the first part from the list and take that as
// the relevant part
// it is somewhat questionnable whether the first part
// gets picked
// but we'll have to take a chance here
Map wsdl4jPartsMap = wsdl4jMessage.getParts();
if (!wsdl4jPartsMap.isEmpty()) {
Part wsdl4jPart = (Part) wsdl4jPartsMap.values()
.toArray()[0];
if (wsdl4jPart.getElementName() != null) {
inMessage.setElementQName(wsdl4jPart
.getElementName());
}
}
}
}
break;
}
}
}
/**
* A reusable method to both the input and output QName populators
*
* @param bindingPartsList
* @param wsdl4jMessage
* @param axisMessage
*/
private void processPartsList(List bindingPartsList, Message wsdl4jMessage,
AxisMessage axisMessage) {
if (bindingPartsList.size() > 1) {
// do something here - perhaps throw and exception
} else {
// find the part from the relevant message
Part wsdl4jMessagePart = wsdl4jMessage
.getPart((String) bindingPartsList.get(0));
// the part name better be there - if not throw an exception
if (wsdl4jMessagePart == null) {
throw new WSDLProcessingException("Missing part named \""
+ bindingPartsList.get(0) + "\"");
}
QName name = wsdl4jMessagePart.getElementName();
if (name == null) {
name = wsdl4jMessagePart.getTypeName();
}
if (name == null) {
throw new WSDLProcessingException(
"Element reference / Type name missing for "
+ bindingPartsList.get(0) + "!");
}
axisMessage.setElementQName(wsdl4jMessagePart.getElementName());
}
}
/**
* Add the QName for the binding output
*
* @param outMessage
* @param wsdl4jOperation
* @param isWrapped
*/
private void AddQNameReference(AxisMessage outMessage,
Operation wsdl4jOperation, BindingOutput bindingOutput,
boolean isWrapped) {
List extensibilityElements = bindingOutput.getExtensibilityElements();
if (wsdl4jOperation.getOutput() == null) {
return;
}
Message wsdl4jMessage = wsdl4jOperation.getOutput().getMessage();
for (int i = 0; i < extensibilityElements.size(); i++) {
ExtensibilityElement extElement = (ExtensibilityElement) extensibilityElements
.get(i);
// SOAP 1.1 body element found!
if (extElement instanceof SOAPBody) {
SOAPBody soapBody = (SOAPBody) extElement;
List bindingPartsList = soapBody.getParts();
if (bindingPartsList != null && !bindingPartsList.isEmpty()) {
// we can process a single part only so delegate the task
// of processing
processPartsList(bindingPartsList, wsdl4jMessage,
outMessage);
// there are no parts named in the binding - process the
// items normally
// by looking at the single message part - or the wrapped
// items if wrapped by us
} else {
// for the wrapped types we need to find this from the
// wrapper schema map
if (isWrapped) {
// The schema for this should be already made ! Find the
// QName from
// the list and add it
outMessage
.setElementQName((QName) resolvedRpcWrappedElementMap
.get(wsdl4jOperation.getName()
+ WRAPPED_OUTPUTNAME_SUFFIX));
} else if (wsdl4jMessage != null) {
// pick the first part from the list and take that as
// the relevant part
// it is somewhat questionable whether the first part
// gets picked
// but we'll have to take a chance here
Map wsdl4jPartsMap = wsdl4jMessage.getParts();
if (!wsdl4jPartsMap.isEmpty()) {
Part wsdl4jPart = (Part) wsdl4jPartsMap.values()
.toArray()[0];
if (wsdl4jPart.getElementName() != null) {
outMessage.setElementQName(wsdl4jPart
.getElementName());
}
}
}
}
} else if (extElement instanceof SOAP12Body) {
SOAP12Body soapBody = (SOAP12Body) extElement;
List bindingPartsList = soapBody.getParts();
if (bindingPartsList != null && !bindingPartsList.isEmpty()) {
// we can process a single part only
processPartsList(bindingPartsList, wsdl4jMessage, outMessage);
// there are no parts named in the binding - process the
// items normally
// by looking at the single message part - or the wrapped
// items if wrapped by us
} else {
// for the wrapped types we need to find this from the
// wrapper schema map
if (isWrapped) {
// The schema for this should be already made ! Find the
// QName from
// the list and add it - the name for this is just the
outMessage
.setElementQName((QName) resolvedRpcWrappedElementMap
.get(wsdl4jOperation.getName()
+ WRAPPED_OUTPUTNAME_SUFFIX));
} else if (wsdl4jMessage != null) {
// pick the first part from the list and take that as
// the relevant part
// it is somewhat questionnable whether the first part
// gets picked
// but we'll have to take a chance here
Map wsdl4jPartsMap = wsdl4jMessage.getParts();
if (!wsdl4jPartsMap.isEmpty()) {
Part wsdl4jPart = (Part) wsdl4jPartsMap.values()
.toArray()[0];
if (wsdl4jPart.getElementName() != null) {
outMessage.setElementQName(wsdl4jPart
.getElementName());
}
}
}
}
}
}
}
/**
* Add the QName for the binding output
*/
private void AddQNameReference(AxisMessage faultMessage,
Message wsdl4jMessage) throws AxisFault {
// for a fault this is trivial - All faults are related directly to a
// message by the name and are supposed to have a single part. So it is
// a matter of copying the right QName from the message part
// get the part
Part wsdl4jMessagePart = (Part) wsdl4jMessage.getParts().values()
.toArray()[0];
if (wsdl4jMessagePart == null) {
throw new WSDLProcessingException();
}
QName name = wsdl4jMessagePart.getElementName();
if (name == null) {
String message = "Part '" + wsdl4jMessagePart.getName() +
"' of fault message '" + wsdl4jMessage.getQName()
+ "' must be defined with 'element=QName' and not 'type=QName'";
log.error(message);
throw new AxisFault(message);
}
faultMessage.setElementQName(name);
}
/**
* A util method that returns the SOAP style included in the binding
* operation
*
* @param bindingOp
*/
private String getSOAPStyle(BindingOperation bindingOp) {
List extensibilityElements = bindingOp.getExtensibilityElements();
for (int i = 0; i < extensibilityElements.size(); i++) {
Object extElement = extensibilityElements.get(i);
if (extElement instanceof SOAPOperation) {
return ((SOAPOperation) extElement).getStyle();
} else if (extElement instanceof SOAP12Operation) {
return ((SOAP12Operation) extElement).getStyle();
}
}
return null;
}
/**
* Simply Copy information.
*
* @param wsdl4jPortType
*/
// FIXME Evaluate a way of injecting features and priperties with a general
// formatted input
private void processPortType(PortType wsdl4jPortType, Definition dif)
throws Exception {
copyExtensionAttributes(wsdl4jPortType.getExtensionAttributes(),
axisService, PORT_TYPE);
// set port the type name
axisService.setPortTypeName(wsdl4jPortType.getQName().getLocalPart());
Iterator wsdl4JOperationsIterator = wsdl4jPortType.getOperations()
.iterator();
Operation wsdl4jOperation;
while (wsdl4JOperationsIterator.hasNext()) {
wsdl4jOperation = (Operation) wsdl4JOperationsIterator.next();
axisService.addOperation(populateOperations(wsdl4jOperation,
wsdl4jPortType, dif));
}
}
/**
* Copy the component from the operation
*
* @param wsdl4jOperation
* @param dif
* @throws Exception
*/
private AxisOperation populateOperations(Operation wsdl4jOperation,
PortType wsdl4jPortType, Definition dif) throws Exception {
QName opName = new QName(wsdl4jOperation.getName());
// Copy Name Attribute
AxisOperation axisOperation = axisService.getOperation(opName);
if (axisOperation == null) {
String MEP = getMEP(wsdl4jOperation);
axisOperation = AxisOperationFactory.getOperationDescription(MEP);
axisOperation.setName(opName);
// setting the PolicyInclude property of the AxisOperation
PolicyInclude policyInclude = new PolicyInclude(axisOperation);
axisOperation.setPolicyInclude(policyInclude);
}
copyExtensibleElements(wsdl4jOperation.getExtensibilityElements(), dif,
axisOperation, PORT_TYPE_OPERATION);
Input wsdl4jInputMessage = wsdl4jOperation.getInput();
if (isServerSide) {
if (null != wsdl4jInputMessage) {
AxisMessage inMessage = axisOperation
.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
Message message = wsdl4jInputMessage.getMessage();
if (null != message) {
inMessage.setName(message.getQName().getLocalPart());
copyExtensibleElements(message.getExtensibilityElements(),
dif, inMessage, PORT_TYPE_OPERATION_INPUT);
}
// Check if the action is already set as we don't want to
// override it
// with the Default Action Pattern
ArrayList inputActions = axisOperation.getWsamappingList();
String action = null;
if (inputActions == null || inputActions.size() == 0) {
action = WSDL11ActionHelper
.getActionFromInputElement(dif, wsdl4jPortType,
wsdl4jOperation, wsdl4jInputMessage);
}
if (action != null) {
if (inputActions == null) {
inputActions = new ArrayList();
axisOperation.setWsamappingList(inputActions);
}
inputActions.add(action);
}
}
// Create an output message and add
Output wsdl4jOutputMessage = wsdl4jOperation.getOutput();
if (null != wsdl4jOutputMessage) {
AxisMessage outMessage = axisOperation
.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
Message message = wsdl4jOutputMessage.getMessage();
if (null != message) {
outMessage.setName(message.getQName().getLocalPart());
copyExtensibleElements(message.getExtensibilityElements(),
dif, outMessage, PORT_TYPE_OPERATION_OUTPUT);
// wsdl:portType -> wsdl:operation -> wsdl:output
}
// Check if the action is already set as we don't want to
// override it
// with the Default Action Pattern
String action = axisOperation.getOutputAction();
if (action == null) {
action = WSDL11ActionHelper.getActionFromOutputElement(dif,
wsdl4jPortType, wsdl4jOperation,
wsdl4jOutputMessage);
}
if (action != null) {
axisOperation.setOutputAction(action);
}
}
} else {
// for the client side we have to do something that is a bit
// weird. The in message is actually taken from the output
// and the output is taken from the in
if (null != wsdl4jInputMessage) {
AxisMessage inMessage = axisOperation
.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
Message message = wsdl4jInputMessage.getMessage();
if (null != message) {
inMessage.setName(message.getQName().getLocalPart());
copyExtensibleElements(message.getExtensibilityElements(),
dif, inMessage, PORT_TYPE_OPERATION_OUTPUT);
}
// Check if the action is already set as we don't want to
// override it
// with the Default Action Pattern
String action = axisOperation.getOutputAction();
if (action == null) {
action = WSDL11ActionHelper
.getActionFromInputElement(dif, wsdl4jPortType,
wsdl4jOperation, wsdl4jInputMessage);
}
if (action != null) {
axisOperation.setOutputAction(action);
}
}
// Create an output message and add
Output wsdl4jOutputMessage = wsdl4jOperation.getOutput();
if (null != wsdl4jOutputMessage) {
AxisMessage outMessage = axisOperation
.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
Message message = wsdl4jOutputMessage.getMessage();
if (null != message) {
outMessage.setName(message.getQName().getLocalPart());
copyExtensibleElements(message.getExtensibilityElements(),
dif, outMessage, PORT_TYPE_OPERATION_INPUT);
// wsdl:portType -> wsdl:operation -> wsdl:output
}
// Check if the action is already set as we don't want to
// override it
// with the Default Action Pattern
ArrayList inputActions = axisOperation.getWsamappingList();
String action = null;
if (inputActions == null || inputActions.size() == 0) {
action = WSDL11ActionHelper.getActionFromOutputElement(dif,
wsdl4jPortType, wsdl4jOperation,
wsdl4jOutputMessage);
}
if (action != null) {
if (inputActions == null) {
inputActions = new ArrayList();
axisOperation.setWsamappingList(inputActions);
}
inputActions.add(action);
}
}
}
Map faults = wsdl4jOperation.getFaults();
Iterator faultKeyIterator = faults.keySet().iterator();
while (faultKeyIterator.hasNext()) {
Fault fault = (Fault) faults.get(faultKeyIterator.next());
AxisMessage axisFaultMessage = new AxisMessage();
Message faultMessage = fault.getMessage();
if (null != faultMessage) {
axisFaultMessage
.setName(faultMessage.getQName().getLocalPart());
copyExtensibleElements(faultMessage.getExtensibilityElements(),
dif, axisFaultMessage, PORT_TYPE_OPERATION_FAULT);
}
// Check if the action is already set as we don't want to override
// it
// with the Default Action Pattern
String action = axisOperation.getFaultAction(fault.getName());
if (action == null) {
action = WSDL11ActionHelper.getActionFromFaultElement(dif,
wsdl4jPortType, wsdl4jOperation, fault);
}
if (action != null) {
axisOperation.addFaultAction(fault.getName(), action);
}
axisOperation.setFaultMessages(axisFaultMessage);
}
return axisOperation;
}
/**
* Generates a list of wrapper schemas
*
* @param wsdl4jBinding
*/
private Element[] generateWrapperSchema(Map schemaMap, Binding wsdl4jBinding) {
List schemaElementList = new ArrayList();
// target namespace for this should be the namespace URI for
// the porttype
String porttypeNamespaceURI = wsdl4jBinding.getPortType().getQName()
.getNamespaceURI();
// //////////////////////////////////////////////////////////////////////
// if there are any bindings present then we have to process them. we
// have to generate a schema per wsdl4jBinding (that is the safest
// option).
// if not we just resolve to
// the good old port type
// list, in which case we'll generate a schema per porttype
// //////////////////////////////////////////////////////////////////////
Element schemaElement = createSchemaForPorttype(porttypeNamespaceURI,
findWrappableOperations(wsdl4jBinding), schemaMap);
if (schemaElement != null) {
schemaElementList.add(schemaElement);
}
return (Element[]) schemaElementList
.toArray(new Element[schemaElementList.size()]);
}
/**
* Create a schema by looking at the port type
*
* @param namespaceURI
* @return null if there is no element
*/
private Element createSchemaForPorttype(String namespaceURI,
List operationListToProcess, Map existingSchemaMap) {
// first of all look at the operations list
// we can return immediately if we get the operations list
// as empty
if (operationListToProcess.isEmpty()) {
return null;
}
// loop through the messages. We'll populate thins map with the relevant
// messages
// from the operations
Map messagesMap = new HashMap();
Map inputOperationsMap = new HashMap();
Map outputOperationsMap = new HashMap();
Map faultyOperationsMap = new HashMap();
// this contains the required namespace imports. the key in this
// map would be the namaspace URI
Map namespaceImportsMap = new HashMap();
// generated complextypes. Keep in the list for writing later
// the key for the complexType map is the message QName
Map complexTypeElementsMap = new HashMap();
// generated Elements. Kep in the list for later writing
List elementElementsList = new ArrayList();
// list namespace prefix map. This map will include uri -> prefix
Map namespacePrefixMap = new HashMap();
// //////////////////////////////////////////////////////////////////////////////////////////////////
// First thing is to populate the message map with the messages to
// process.
// //////////////////////////////////////////////////////////////////////////////////////////////////
// we really need to do this for a single porttype!
Operation op;
for (int k = 0; k < operationListToProcess.size(); k++) {
op = (Operation) operationListToProcess.get(k);
Input input = op.getInput();
Message message;
if (input != null) {
message = input.getMessage();
messagesMap.put(message.getQName(), message);
inputOperationsMap.put(op.getName(), message);
}
Output output = op.getOutput();
if (output != null) {
message = output.getMessage();
messagesMap.put(message.getQName(), message);
outputOperationsMap.put(op.getName(), message);
}
Map faultMap = op.getFaults();
if (faultMap != null && faultMap.size() > 0) {
Iterator keys = faultMap.keySet().iterator();
while (keys.hasNext()) {
Object key = keys.next();
Fault fault = (Fault) faultMap.get(key);
if (fault != null) {
message = fault.getMessage();
messagesMap.put(message.getQName(), message);
faultyOperationsMap.put(key, message);
}
}
}
}
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// check whether there are messages that are wrappable. If there are no
// messages that are wrappable we'll
// just return null and endup this process. However we need to take the
// force flag into account here
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
QName[] keys;
// just take all the messages and wrap them, we've already selected
// the relevant messages by looking at the SOAP binding
keys = (QName[]) messagesMap.keySet().toArray(
new QName[messagesMap.size()]);
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now we have the message list to process - Process the whole list of
// messages at once
// since we need to generate one single schema
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
List resolvedMessageQNames = new ArrayList();
// find the xsd prefix
String xsdPrefix = findSchemaPrefix();
Message wsdl4jMessage;
// DOM document that will be the ultimate creator
Document document = getDOMDocumentBuilder().newDocument();
for (int i = 0; i < keys.length; i++) {
wsdl4jMessage = (Message) messagesMap.get(keys[i]);
// No need to check the wrappable,
// This message is wrappabel. However we need to see whether the
// message is already
// resolved!
if (!resolvedMessageQNames.contains(wsdl4jMessage.getQName())) {
// This message has not been touched before!. So we can go ahead
// now
Map parts = wsdl4jMessage.getParts();
// add the complex type
Element newComplexType = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_COMPLEX_TYPE_LOCAL_NAME);
Element cmplxTypeSequence = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_SEQUENCE_LOCAL_NAME);
Element child;
Iterator iterator = parts.keySet().iterator();
while (iterator.hasNext()) {
Part part = (Part) parts.get(iterator.next());
// the part name
String elementName = part.getName();
boolean isTyped = true;
// the type name
QName schemaTypeName;
if (part.getTypeName() != null) {
schemaTypeName = part.getTypeName();
} else if (part.getElementName() != null) {
schemaTypeName = part.getElementName();
isTyped = false;
} else {
throw new RuntimeException(" Unqualified Message part!");
}
child = document.createElementNS(XMLSCHEMA_NAMESPACE_URI,
xsdPrefix + ":" + XML_SCHEMA_ELEMENT_LOCAL_NAME);
String prefix;
if (XMLSCHEMA_NAMESPACE_URI.equals(schemaTypeName
.getNamespaceURI())) {
prefix = xsdPrefix;
} else {
// this schema is a third party one. So we need to have
// an import statement in our generated schema
String uri = schemaTypeName.getNamespaceURI();
if (!namespaceImportsMap.containsKey(uri)) {
// create Element for namespace import
Element namespaceImport = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_IMPORT_LOCAL_NAME);
namespaceImport.setAttribute(NAMESPACE_URI, uri);
// add this to the map
namespaceImportsMap.put(uri, namespaceImport);
// we also need to associate this uri with a prefix
// and include that prefix
// in the schema's namspace declarations. So add
// theis particular namespace to the
// prefix map as well
prefix = getTemporaryNamespacePrefix();
namespacePrefixMap.put(uri, prefix);
} else {
// this URI should be already in the namspace prefix
// map
prefix = (String) namespacePrefixMap.get(uri);
}
}
// If it's from a type the element we need to add a name and
// the type
// if not it's the element reference
if (isTyped) {
child.setAttribute(XSD_NAME, elementName);
child.setAttribute(XSD_TYPE, prefix + ":"
+ schemaTypeName.getLocalPart());
} else {
child.setAttribute(XSD_REF, prefix + ":"
+ schemaTypeName.getLocalPart());
}
cmplxTypeSequence.appendChild(child);
}
newComplexType.appendChild(cmplxTypeSequence);
// add this newly created complextype to the list
complexTypeElementsMap.put(wsdl4jMessage.getQName(),
newComplexType);
resolvedMessageQNames.add(wsdl4jMessage.getQName());
}
}
Element elementDeclaration;
// loop through the input op map and generate the elements
String[] inputOperationtNames = (String[]) inputOperationsMap.keySet()
.toArray(new String[inputOperationsMap.size()]);
for (int j = 0; j < inputOperationtNames.length; j++) {
String inputOpName = inputOperationtNames[j];
elementDeclaration = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_ELEMENT_LOCAL_NAME);
elementDeclaration.setAttribute(XSD_NAME, inputOpName);
QName typeQName = ((Message) inputOperationsMap.get(inputOpName))
.getQName();
// add the anonymous
elementDeclaration.appendChild(((Element) complexTypeElementsMap
.get(typeQName)).cloneNode(true));
elementElementsList.add(elementDeclaration);
resolvedRpcWrappedElementMap.put(inputOpName, new QName(
namespaceURI, inputOpName, AXIS2WRAPPED));
}
// loop through the output op map and generate the elements
String[] outputOperationtNames = (String[]) outputOperationsMap
.keySet().toArray(new String[outputOperationsMap.size()]);
for (int j = 0; j < outputOperationtNames.length; j++) {
String baseoutputOpName = outputOperationtNames[j];
String outputOpName = baseoutputOpName + WRAPPED_OUTPUTNAME_SUFFIX;
elementDeclaration = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_ELEMENT_LOCAL_NAME);
elementDeclaration.setAttribute(XSD_NAME, outputOpName);
QName typeQName = ((Message) outputOperationsMap
.get(baseoutputOpName)).getQName();
// add the anonymous
elementDeclaration.appendChild(((Element) complexTypeElementsMap
.get(typeQName)).cloneNode(true));
elementElementsList.add(elementDeclaration);
resolvedRpcWrappedElementMap.put(outputOpName, new QName(
namespaceURI, outputOpName, AXIS2WRAPPED));
}
// loop through the faultoutput op map and generate the elements
String[] faultyOperationtNames = (String[]) faultyOperationsMap
.keySet().toArray(new String[faultyOperationsMap.size()]);
for (int j = 0; j < faultyOperationtNames.length; j++) {
String baseFaultOpName = faultyOperationtNames[j];
elementDeclaration = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_ELEMENT_LOCAL_NAME);
elementDeclaration.setAttribute(XSD_NAME, baseFaultOpName);
QName typeQName = ((Message) faultyOperationsMap
.get(baseFaultOpName)).getQName();
elementDeclaration.appendChild(((Element) complexTypeElementsMap
.get(typeQName)).cloneNode(true));
elementElementsList.add(elementDeclaration);
resolvedRpcWrappedElementMap.put(baseFaultOpName, new QName(
namespaceURI, baseFaultOpName, AXIS2WRAPPED));
}
// /////////////////////////////////////////////////////////////////////
//
// Now we are done with processing the messages and generating the right
// schema object model
// time to write out the schema
//
// There is a catch here - when the target namespace of the generated
// schema is equivalent to one of the existing schemas we'll have to
// insert the elements there rather than creating a new Schema element
// //////////////////////////////////////////////////////////////////////
//
if (existingSchemaMap.containsKey(namespaceURI)) {
// get the relevant schema element
Element schemaElement = (Element) existingSchemaMap
.get(namespaceURI);
Document ownerDocument = schemaElement.getOwnerDocument();
// loop through the namespace declarations first and add them
String[] nameSpaceDeclarationArray = (String[]) namespacePrefixMap
.keySet().toArray(new String[namespacePrefixMap.size()]);
for (int i = 0; i < nameSpaceDeclarationArray.length; i++) {
String s = nameSpaceDeclarationArray[i];
checkAndAddNamespaceDeclarations(s, namespacePrefixMap,
schemaElement);
}
// add imports - check whether it is the targetnamespace before
// adding
Element[] namespaceImports = (Element[]) namespaceImportsMap
.values().toArray(new Element[namespaceImportsMap.size()]);
for (int i = 0; i < namespaceImports.length; i++) {
if (!namespaceURI.equals(namespaceImports[i]
.getAttribute(NAMESPACE_URI))) {
schemaElement.appendChild(ownerDocument.importNode(
namespaceImports[i], true));
}
}
Element[] elementDeclarations = (Element[]) elementElementsList
.toArray(new Element[elementElementsList.size()]);
for (int i = 0; i < elementDeclarations.length; i++) {
schemaElement.appendChild(ownerDocument.importNode(
elementDeclarations[i], true));
}
// don't return anything!!
return null;
} else {
// there is no element in the
Element schemaElement = document.createElementNS(
XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
+ XML_SCHEMA_LOCAL_NAME);
// loop through the namespace declarations first
String[] nameSpaceDeclarationArray = (String[]) namespacePrefixMap
.keySet().toArray(new String[namespacePrefixMap.size()]);
for (int i = 0; i < nameSpaceDeclarationArray.length; i++) {
String s = nameSpaceDeclarationArray[i];
schemaElement.setAttributeNS(XML_NAMESPACE_URI,
NAMESPACE_DECLARATION_PREFIX
+ namespacePrefixMap.get(s).toString(), s);
}
if (schemaElement.getAttributeNS(XML_NAMESPACE_URI, xsdPrefix)
.length() == 0) {
schemaElement.setAttributeNS(XML_NAMESPACE_URI,
NAMESPACE_DECLARATION_PREFIX + xsdPrefix,
XMLSCHEMA_NAMESPACE_URI);
}
// add the targetNamespace
schemaElement.setAttributeNS(XML_NAMESPACE_URI, XMLNS_AXIS2WRAPPED,
namespaceURI);
schemaElement.setAttribute(XSD_TARGETNAMESPACE, namespaceURI);
schemaElement.setAttribute(XSD_ELEMENT_FORM_DEFAULT,
XSD_UNQUALIFIED);
// add imports
Element[] namespaceImports = (Element[]) namespaceImportsMap
.values().toArray(new Element[namespaceImportsMap.size()]);
for (int i = 0; i < namespaceImports.length; i++) {
schemaElement.appendChild(namespaceImports[i]);
}
// add element declarations
Element[] elementDeclarations = (Element[]) elementElementsList
.toArray(new Element[elementElementsList.size()]);
for (int i = 0; i < elementDeclarations.length; i++) {
schemaElement.appendChild(elementDeclarations[i]);
}
return schemaElement;
}
}
/**
* @param prefixMap
*/
private void checkAndAddNamespaceDeclarations(String namespace,
Map prefixMap, Element schemaElement) {
// get the attribute for the current namespace
String prefix = (String) prefixMap.get(namespace);
// A prefix must be found at this point!
String existingURL = schemaElement.getAttributeNS(XML_NAMESPACE_URI,
NAMESPACE_DECLARATION_PREFIX + prefix);
if (existingURL == null) {
// there is no existing URL by that prefix - declare a new namespace
schemaElement.setAttributeNS(XML_NAMESPACE_URI,
NAMESPACE_DECLARATION_PREFIX + prefix, namespace);
} else if (existingURL.equals(namespace)) {
// this namespace declaration is already there with the same prefix
// ignore it
} else {
// there is a different namespace declared in the given prefix
// change the prefix in the prefix map to a new one and declare it
// create a prefix
String generatedPrefix = "ns" + prefixCounter++;
while (prefixMap.containsKey(generatedPrefix)) {
generatedPrefix = "ns" + prefixCounter++;
}
schemaElement.setAttributeNS(XML_NAMESPACE_URI,
NAMESPACE_DECLARATION_PREFIX + generatedPrefix, namespace);
// add to the map
prefixMap.put(generatedPrefix, namespace);
}
}
/**
* The intention of this procedure is to process the imports. When
* processing the imports the imported documents will be populating the
* items in the main document recursivley
*
* @param wsdl4JDefinition
*/
private void processImports(Definition wsdl4JDefinition,
List processedDocuments) {
Map wsdlImports = wsdl4JDefinition.getImports();
if (null != wsdlImports && !wsdlImports.isEmpty()) {
Collection importsCollection = wsdlImports.values();
for (Iterator iterator = importsCollection.iterator(); iterator
.hasNext();) {
Vector values = (Vector) iterator.next();
for (int i = 0; i < values.size(); i++) {
Import wsdlImport = (Import) values.elementAt(i);
if (wsdlImport.getDefinition() != null) {
Definition importedDef = wsdlImport.getDefinition();
if (importedDef != null) {
String key = importedDef.getDocumentBaseURI();
if (key == null) {
key = importedDef.getTargetNamespace();
}
// stop recursive imports!
if (processedDocuments.contains(key)) {
return;
}
processedDocuments.add(key);
processImports(importedDef,
processedDocuments);
// copy ns
Map namespaces = importedDef.getNamespaces();
Iterator keys = namespaces.keySet().iterator();
while (keys.hasNext()) {
Object key2 = keys.next();
if (!wsdl4jDefinition.getNamespaces()
.containsValue(namespaces.get(key2))) {
wsdl4jDefinition.getNamespaces().put(key2,
namespaces.get(key2));
}
}
wsdl4jDefinition.getNamespaces().putAll(namespaces);
// copy types
Types t = importedDef.getTypes();
if (t != null) {
List typesList = t.getExtensibilityElements();
for (int j = 0; j < typesList.size(); j++) {
Types types = wsdl4JDefinition.getTypes();
if (types == null) {
types = wsdl4JDefinition.createTypes();
wsdl4JDefinition.setTypes(types);
}
types
.addExtensibilityElement((ExtensibilityElement) typesList
.get(j));
}
}
// add messages
Map messagesMap = importedDef.getMessages();
wsdl4JDefinition.getMessages().putAll(messagesMap);
// add portypes
Map porttypeMap = importedDef.getPortTypes();
wsdl4JDefinition.getPortTypes().putAll(porttypeMap);
// add bindings
Map bindingMap = importedDef.getBindings();
wsdl4JDefinition.getBindings().putAll(bindingMap);
// add services
Map serviceMap = importedDef.getServices();
wsdl4JDefinition.getServices().putAll(serviceMap);
List extElementList = importedDef
.getExtensibilityElements();
wsdl4JDefinition.getExtensibilityElements().addAll(
extElementList);
}
}
}
}
}
}
/**
* Read the WSDL file given the inputstream for the WSDL source
*
* @param in
* @throws WSDLException
*/
private Definition readInTheWSDLFile(InputStream in) throws WSDLException {
WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
// switch off the verbose mode for all usecases
reader.setFeature(JAVAX_WSDL_VERBOSE_MODE_KEY, false);
// if the custem resolver is present then use it
if (customWSLD4JResolver != null) {
return reader.readWSDL(customWSLD4JResolver);
} else {
Document doc;
try {
doc = XMLUtils.newDocument(in);
} catch (ParserConfigurationException e) {
throw new WSDLException(WSDLException.PARSER_ERROR,
"Parser Configuration Error", e);
} catch (SAXException e) {
throw new WSDLException(WSDLException.PARSER_ERROR,
"Parser SAX Error", e);
} catch (IOException e) {
throw new WSDLException(WSDLException.INVALID_WSDL, "IO Error",
e);
}
return reader.readWSDL(getBaseUri(), doc);
}
}
/**
* Get the Extensible elements form wsdl4jExtensibleElements
* <code>Vector</code> if any and copy them to <code>Component</code>
* <p/> Note - SOAP body extensible element will be processed differently
*
* @param wsdl4jExtensibleElements
* @param description where is the ext element (port , portype , biding)
* @param wsdl4jDefinition
* @param originOfExtensibilityElements -
* this will indicate the place this extensibility element came
* from.
*/
private void copyExtensibleElements(List wsdl4jExtensibleElements,
Definition wsdl4jDefinition, AxisDescription description,
String originOfExtensibilityElements) throws AxisFault {
Iterator iterator = wsdl4jExtensibleElements.iterator();
while (iterator.hasNext()) {
ExtensibilityElement wsdl4jElement = (ExtensibilityElement) iterator
.next();
if (wsdl4jElement instanceof UnknownExtensibilityElement) {
UnknownExtensibilityElement unknown = (UnknownExtensibilityElement) (wsdl4jElement);
if (WSDLConstants.WSDL11Constants.POLICY.equals(unknown
.getElementType())) {
Policy policy = (Policy) PolicyUtil
.getPolicyComponent(unknown.getElement());
addPolicy(description, originOfExtensibilityElements,
policy);
} else if (WSDLConstants.WSDL11Constants.POLICY_REFERENCE
.equals(unknown.getElementType())) {
PolicyReference policyReference = (PolicyReference) PolicyUtil
.getPolicyComponent(unknown.getElement());
addPolicyRef(description, originOfExtensibilityElements,
policyReference);
} else if (AddressingConstants.Final.WSAW_USING_ADDRESSING
.equals(unknown.getElementType())
|| AddressingConstants.Submission.WSAW_USING_ADDRESSING
.equals(unknown.getElementType())) {
// Read the wsaw:UsingAddressing flag from the WSDL. It is
// only valid on the Port or Binding
// so only recognise it as en extensibility elemtn of one of
// those.
if (originOfExtensibilityElements.equals(PORT)
|| originOfExtensibilityElements.equals(BINDING)) {
if (Boolean.TRUE.equals(unknown.getRequired())) {
axisService
.setWSAddressingFlag(AddressingConstants.ADDRESSING_REQUIRED);
} else {
axisService
.setWSAddressingFlag(AddressingConstants.ADDRESSING_OPTIONAL);
}
}
} else if (AddressingConstants.Final.WSAW_ANONYMOUS
.equals(unknown.getElementType())) {
if (originOfExtensibilityElements.equals(BINDING_OPERATION)) {
AxisOperation axisOperation = (AxisOperation) description;
if (unknown.getElement().getFirstChild() != null
&& unknown.getElement().getFirstChild()
.getNodeType() == Node.TEXT_NODE) {
String anonymousValue = unknown.getElement()
.getFirstChild().getNodeValue();
AddressingHelper.setAnonymousParameterValue(
axisOperation, anonymousValue);
}
}
} else {
// Ignore this element - it is a totally unknown element
// and we don't care!
}
// WSDL4J has all the SOAP 1.1 and SOAP 1.2 Items built in. So we can check
// the items directly
} else if (wsdl4jElement instanceof SOAP12Address) {
SOAP12Address soapAddress = (SOAP12Address) wsdl4jElement;
axisService.setEndpoint(soapAddress.getLocationURI());
} else if (wsdl4jElement instanceof SOAPAddress) {
SOAPAddress soapAddress = (SOAPAddress) wsdl4jElement;
axisService.setEndpoint(soapAddress.getLocationURI());
} else if (wsdl4jElement instanceof Schema) {
Schema schema = (Schema) wsdl4jElement;
// just add this schema - no need to worry about the imported
// ones
axisService.addSchema(getXMLSchema(schema.getElement(), schema
.getDocumentBaseURI()));
} else if (wsdl4jElement instanceof SOAP12Operation) {
SOAP12Operation soapOperation = (SOAP12Operation) wsdl4jElement;
if (description instanceof AxisOperation) {
AxisOperation axisOperation = (AxisOperation) description;
if (soapOperation.getStyle() != null) {
axisOperation.setStyle(soapOperation.getStyle());
}
axisOperation.setSoapAction(soapOperation
.getSoapActionURI());
}
} else if (wsdl4jElement instanceof SOAPOperation) {
SOAPOperation soapOperation = (SOAPOperation) wsdl4jElement;
if (description instanceof AxisOperation) {
AxisOperation axisOperation = (AxisOperation) description;
if (soapOperation.getStyle() != null) {
axisOperation.setStyle(soapOperation.getStyle());
}
axisOperation.setSoapAction(soapOperation
.getSoapActionURI());
}
} else if (wsdl4jElement instanceof SOAP12Header) {
SOAP12Header soapHeader = (SOAP12Header) wsdl4jElement;
SOAPHeaderMessage headerMessage = new SOAPHeaderMessage();
headerMessage.setNamespaceURI(soapHeader.getNamespaceURI());
headerMessage.setUse(soapHeader.getUse());
Boolean required = soapHeader.getRequired();
if (null != required) {
headerMessage.setRequired(required.booleanValue());
}
if (null != wsdl4jDefinition) {
// find the relevant schema part from the messages
Message msg = wsdl4jDefinition.getMessage(soapHeader
.getMessage());
if (msg == null) {
// todo i18n this
throw new AxisFault("message "
+ soapHeader.getMessage()
+ " not found in the WSDL ");
}
Part msgPart = msg.getPart(soapHeader.getPart());
if (msgPart == null) {
// todo i18n this
throw new AxisFault("message part "
+ soapHeader.getPart()
+ " not found in the WSDL ");
}
headerMessage.setElement(msgPart.getElementName());
}
headerMessage.setMessage(soapHeader.getMessage());
headerMessage.setPart(soapHeader.getPart());
if (description instanceof AxisMessage) {
((AxisMessage) description).addSoapHeader(headerMessage);
}
} else if (wsdl4jElement instanceof SOAPHeader) {
SOAPHeader soapHeader = (SOAPHeader) wsdl4jElement;
SOAPHeaderMessage headerMessage = new SOAPHeaderMessage();
headerMessage.setNamespaceURI(soapHeader.getNamespaceURI());
headerMessage.setUse(soapHeader.getUse());
Boolean required = soapHeader.getRequired();
if (null != required) {
headerMessage.setRequired(required.booleanValue());
}
if (null != wsdl4jDefinition) {
// find the relevant schema part from the messages
Message msg = wsdl4jDefinition.getMessage(soapHeader
.getMessage());
if (msg == null) {
// todo i18n this
throw new AxisFault("message "
+ soapHeader.getMessage()
+ " not found in the WSDL ");
}
Part msgPart = msg.getPart(soapHeader.getPart());
if (msgPart == null) {
// todo i18n this
throw new AxisFault("message part "
+ soapHeader.getPart()
+ " not found in the WSDL ");
}
headerMessage.setElement(msgPart.getElementName());
}
headerMessage.setMessage(soapHeader.getMessage());
headerMessage.setPart(soapHeader.getPart());
if (description instanceof AxisMessage) {
((AxisMessage) description).addSoapHeader(headerMessage);
}
} else if (wsdl4jElement instanceof SOAPBinding) {
SOAPBinding soapBinding = (SOAPBinding) wsdl4jElement;
style = soapBinding.getStyle();
axisService.setSoapNsUri(soapBinding.getElementType()
.getNamespaceURI());
} else if (wsdl4jElement instanceof SOAP12Binding) {
SOAP12Binding soapBinding = (SOAP12Binding) wsdl4jElement;
style = soapBinding.getStyle();
axisService.setSoapNsUri(soapBinding.getElementType()
.getNamespaceURI());
}
}
}
/**
* Add a policy
*
* @param description
* @param originOfExtensibilityElements
* @param policy
*/
private void addPolicy(AxisDescription description,
String originOfExtensibilityElements, Policy policy) {
if (description instanceof AxisService) {
// wsdl:service
if (SERVICE.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.SERVICE_POLICY, policy);
// wsdl:service -> wsdl:port
} else if (PORT.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.PORT_POLICY, policy);
// wsdl:binding
} else if (BINDING.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.BINDING_POLICY, policy);
}
// TODO wsdl:portType ?
} else if (description instanceof AxisOperation) {
// wsdl:portType -> wsdl:operation
if (PORT_TYPE_OPERATION.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.OPERATION_POLICY, policy);
// wsdl:binding -> wsdl:operation
} else {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.BINDING_OPERATION_POLICY, policy);
}
} else {
// wsdl:portType -> wsdl:operation -> wsdl:input
if (PORT_TYPE_OPERATION_INPUT.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.INPUT_POLICY, policy);
// wsdl:binding -> wsdl:operation -> wsdl:input
} else if (BINDING_OPERATION_INPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.BINDING_INPUT_POLICY, policy);
// wsdl:portType -> wsdl:operation -> wsdl:put
} else if (PORT_TYPE_OPERATION_OUTPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.OUTPUT_POLICY, policy);
// wsdl:binding -> wsdl:operation -> wsdl:output
} else if (BINDING_OPERATION_OUTPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyElement(
PolicyInclude.BINDING_OUTPUT_POLICY, policy);
}
}
}
/**
* Add a policy reference
*
* @param description
* @param originOfExtensibilityElements
* @param policyRefElement
*/
private void addPolicyRef(AxisDescription description,
String originOfExtensibilityElements,
PolicyReference policyRefElement) {
if (description instanceof AxisService) {
// wsdl:service
if (SERVICE.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.SERVICE_POLICY, policyRefElement);
// wsdl:service -> wsdl:port
} else if (PORT.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.PORT_POLICY, policyRefElement);
// wsdl:binding
} else if (BINDING.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.BINDING_POLICY, policyRefElement);
}
// TODO policy for wsdl:portType ?
} else if (description instanceof AxisOperation) {
// wsdl:portType -> wsdl:operation
if (PORT_TYPE_OPERATION.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.OPERATION_POLICY, policyRefElement);
// wsdl:binding -> wsdl:operation
} else {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.BINDING_POLICY, policyRefElement);
}
} else {
// wsdl:portType -> wsdl:operation -> wsdl:input
if (PORT_TYPE_OPERATION_INPUT.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.INPUT_POLICY, policyRefElement);
// wsdl:binding -> wsdl:operation -> wsdl:input
} else if (BINDING_OPERATION_INPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.BINDING_INPUT_POLICY, policyRefElement);
// wsdl:portType -> wsdl:operation -> wsdl:put
} else if (PORT_TYPE_OPERATION_OUTPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.OUTPUT_POLICY, policyRefElement);
// wsdl:binding -> wsdl:operation -> wsdl:output
} else if (BINDING_OPERATION_OUTPUT
.equals(originOfExtensibilityElements)) {
description.getPolicyInclude().addPolicyRefElement(
PolicyInclude.BINDING_OUTPUT_POLICY, policyRefElement);
}
// TODO Faults ..
}
}
/**
* Look for the wrappable operations depending on the style
*
* @param binding
*/
private List findWrappableOperations(Binding binding) {
// first find the global style declaration.
// for a SOAP binding this can be only rpc or document
// as per the WSDL spec (section 3.4) the default style is document
boolean isRPC = false;
boolean isSOAPBinding = false;
List extElements = binding.getExtensibilityElements();
for (int i = 0; i < extElements.size(); i++) {
if (extElements.get(i) instanceof SOAPBinding) {
// we have a global SOAP binding!
isSOAPBinding = true;
SOAPBinding soapBinding = (SOAPBinding) extElements.get(i);
if (RPC_STYLE.equals(soapBinding.getStyle())) {
// set the global style to rpc
isRPC = true;
}
break;
}
}
// if SOAPBinding is not present just return an empty list
if (!isSOAPBinding) {
return new ArrayList();
}
// go through every operation and get their styles.
// each one can have a style override from the global
// styles. Depending on the style add the relevant operations
// to the return list
List returnList = new ArrayList();
BindingOperation bindingOp;
for (Iterator bindingOperationsIterator = binding
.getBindingOperations().iterator(); bindingOperationsIterator
.hasNext();) {
bindingOp = (BindingOperation) bindingOperationsIterator.next();
String style = getSOAPStyle(bindingOp);
if (style == null) {
// no style specified
// use the global style to determine whether to put this one or
// not
if (isRPC) {
returnList.add(bindingOp.getOperation());
}
} else if (RPC_STYLE.equals(style)) {
// add to the list
returnList.add(bindingOp.getOperation());
}
// if not RPC we just leave it - default is doc
}
// set this to the global list
wrappableOperations = returnList;
return returnList;
}
/**
* Guess the MEP based on the order of messages
*
* @param operation
* @throws Exception
*/
private String getMEP(Operation operation) throws Exception {
OperationType operationType = operation.getStyle();
if (isServerSide) {
if (null != operationType) {
if (operationType.equals(OperationType.REQUEST_RESPONSE))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_IN_OUT;
if (operationType.equals(OperationType.ONE_WAY)) {
if (operation.getFaults().size() > 0) {
return WSDLConstants.WSDL20_2004Constants.MEP_URI_ROBUST_IN_ONLY;
}
return WSDLConstants.WSDL20_2004Constants.MEP_URI_IN_ONLY;
}
if (operationType.equals(OperationType.NOTIFICATION))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_OUT_ONLY;
if (operationType.equals(OperationType.SOLICIT_RESPONSE))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_OUT_IN;
throw new Exception("Cannot Determine the MEP");
}
} else {
if (null != operationType) {
if (operationType.equals(OperationType.REQUEST_RESPONSE))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_OUT_IN;
if (operationType.equals(OperationType.ONE_WAY))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_OUT_ONLY;
if (operationType.equals(OperationType.NOTIFICATION))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_IN_ONLY;
if (operationType.equals(OperationType.SOLICIT_RESPONSE))
return WSDLConstants.WSDL20_2004Constants.MEP_URI_IN_OUT;
throw new Exception("Cannot Determine the MEP");
}
}
throw new Exception("Cannot Determine the MEP");
}
/**
* Copies the extension attributes
*
* @param extAttributes
* @param description
* @param origin
*/
private void copyExtensionAttributes(Map extAttributes,
AxisDescription description, String origin) {
QName key;
QName value;
for (Iterator iterator = extAttributes.keySet().iterator(); iterator
.hasNext();) {
key = (QName) iterator.next();
if (Constants.URI_POLICY_NS.equals(key.getNamespaceURI())
&& "PolicyURIs".equals(key.getLocalPart())) {
value = (QName) extAttributes.get(key);
String policyURIs = value.getLocalPart();
if (policyURIs.length() != 0) {
String[] uris = policyURIs.split(" ");
PolicyReference ref;
for (int i = 0; i < uris.length; i++) {
ref = new PolicyReference();
ref.setURI(uris[i]);
if (PORT_TYPE.equals(origin)) {
PolicyInclude include = description
.getPolicyInclude();
include.addPolicyRefElement(
PolicyInclude.PORT_TYPE_POLICY, ref);
}
}
}
}
}
}
/**
* Process the policy definitions
*
* @param definition
*/
private void processPoliciesInDefintion(Definition definition) {
List extElements = definition.getExtensibilityElements();
ExtensibilityElement extElement;
for (Iterator iterator = extElements.iterator(); iterator.hasNext();) {
extElement = (ExtensibilityElement) iterator.next();
if (extElement instanceof UnknownExtensibilityElement) {
UnknownExtensibilityElement unknown = (UnknownExtensibilityElement) extElement;
if (WSDLConstants.WSDL11Constants.POLICY.equals(unknown
.getElementType())) {
Policy policy = (Policy) PolicyUtil
.getPolicyComponent(unknown.getElement());
String key;
if ((key = policy.getName()) != null
|| (key = policy.getId()) != null) {
registry.register(key, policy);
}
}
}
}
}
/**
* Inner class declaration for the processing exceptions
*/
public static class WSDLProcessingException extends RuntimeException {
public WSDLProcessingException() {
}
public WSDLProcessingException(String message) {
super(message);
}
public WSDLProcessingException(Throwable cause) {
super(cause);
}
public WSDLProcessingException(String message, Throwable cause) {
super(message, cause);
}
}
}