org.switchyard.component.soap.util.WSDLUtil Maven / Gradle / Ivy
/*
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors.
*
* 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.
*/
package org.switchyard.component.soap.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Import;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.OperationType;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.extensions.schema.SchemaImport;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.wsdl.extensions.soap12.SOAP12Operation;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import org.jboss.logging.Logger;
import org.switchyard.ExchangePattern;
import org.switchyard.common.type.Classes;
import org.switchyard.common.xml.XMLHelper;
import org.switchyard.component.soap.SOAPMessages;
import org.switchyard.component.soap.Feature;
import org.switchyard.component.soap.PortName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* Contains utility methods to examine/manipulate WSDLs.
*
* @author Magesh Kumar B (C) 2011 Red Hat Inc.
*/
public final class WSDLUtil {
private static final Logger LOGGER = Logger.getLogger(WSDLUtil.class);
/**
* WSDL SOAP 1.1 QName namespace.
*/
public static final String WSDL_SOAP11_URI = "http://schemas.xmlsoap.org/wsdl/soap/";
/**
* WSDL SOAP 1.2 QName namespace.
*/
public static final String WSDL_SOAP12_URI = "http://schemas.xmlsoap.org/wsdl/soap12/";
/**
* Document style.
*/
public static final String DOCUMENT = "document";
private static final String SCHEME_URN = "urn:";
private static final String STR_ACTION = "Action";
private static final String STR_COLON = ":";
private static final String STR_SLASH = "/";
private static final String STR_FAULT = "Fault";
private static final String REQUEST_SUFFIX = "Request";
private static final String RESPONSE_SUFFIX = "Response";
private static final String ATTR_ID = "Id";
private static final String ATTR_REQUIRED = "required";
private static final String ATTR_URI = "URI";
private static final String ATTR_EXP_CT = "expectedContentTypes";
private static final String ATTR_LOCATION = "location";
private static final String ELE_ADDRESSING = "Addressing";
private static final String ELE_ALL = "All";
private static final String ELE_EXACTLYONE = "ExactlyOne";
private static final String ELE_MTOM = "MTOM";
private static final String WSA_METADATA_URI = "http://www.w3.org/2007/05/addressing/metadata";
private static final String WSA_WSDL_URI = "http://www.w3.org/2006/05/addressing/wsdl";
private static final String POLICY_URI = "http://www.w3.org/ns/ws-policy";
private static final String WS_MTOM_URI = "http://www.w3.org/2007/08/soap12-mtom-policy";
private static final String WSDL_XMIME_URI = "http://www.w3.org/2005/05/xmlmime";
private static final String SECURITY_UTILITY_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
// No support for WSDL2.0 yet, as CXF doesn't have it.
// http://cxf.apache.org/project-status.html - GSoC project just started
// private static final String WSDL20_URI = "http://www.w3.org/2006/01/wsdl";
private static final String WSDL11_URI = "http://schemas.xmlsoap.org/wsdl/";
private static final QName USING_WSA_QNAME = new QName(WSA_WSDL_URI, "UsingAddressing");
private static final QName POLICY_QNAME = new QName(POLICY_URI, "Policy");
private static final QName POLICY_REFERENCE_QNAME = new QName(POLICY_URI, "PolicyReference");
private static final QName POLICY_EXACTLYONE_QNAME = new QName(POLICY_URI, ELE_EXACTLYONE);
private static final QName POLICY_ALL_QNAME = new QName(POLICY_URI, ELE_ALL);
private static final QName WSA_QNAME = new QName(WSA_METADATA_URI, ELE_ADDRESSING);
private static final QName WSDL_ACTION_QNAME = new QName(WSA_WSDL_URI, STR_ACTION);
private static final QName WSDL_MTOM_QNAME = new QName(WS_MTOM_URI, ELE_MTOM);
private static final QName MTOM_EXPT_QNAME = new QName(WSDL_XMIME_URI, ATTR_EXP_CT);
private WSDLUtil() {
}
/**
* Read the WSDL document and create a WSDL Definition.
*
* @param wsdlLocation location pointing to a WSDL XML definition.
* @return the Definition.
* @throws WSDLException If unable to read the WSDL
*/
public static Definition readWSDL(final String wsdlLocation) throws WSDLException {
InputStream inputStream = null;
try {
URL url = getURL(wsdlLocation);
inputStream = url.openStream();
InputSource source = new InputSource(inputStream);
source.setSystemId(url.toString());
Document wsdlDoc = XMLHelper.getDocument(source);
WSDLFactory wsdlFactory = WSDLFactory.newInstance();
WSDLReader reader = wsdlFactory.newWSDLReader();
reader.setFeature("javax.wsdl.verbose", false);
return reader.readWSDL(url.toString(), wsdlDoc);
} catch (Exception e) {
throw new WSDLException(WSDLException.OTHER_ERROR,
SOAPMessages.MESSAGES.unableToReadWSDL(wsdlLocation), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ioe) {
LOGGER.error(ioe);
}
}
}
}
/**
* Read the WSDL document accessible via the specified
* URI into a StreamSource.
*
* @param wsdlURI a URI (can be a filename or URL) pointing to a
* WSDL XML definition.
* @return the StreamSource.
* @throws WSDLException If unable to read the WSDL
*/
public static StreamSource getStream(final String wsdlURI) throws WSDLException {
try {
URL url = getURL(wsdlURI);
InputStream inputStream = url.openStream();
StreamSource inputSource = new StreamSource(inputStream);
inputSource.setSystemId(url.toString());
return inputSource;
} catch (Exception e) {
throw new WSDLException(WSDLException.OTHER_ERROR,
SOAPMessages.MESSAGES.unableToResolveWSDL(wsdlURI.toString()), e);
}
}
/**
* Convert a path/uri to a URL.
*
* @param path a path or URI.
* @return the URL.
* @throws MalformedURLException If the url path is not valid
*/
public static URL getURL(final String path) throws MalformedURLException {
if (path.startsWith("http://") || path.startsWith("https://") || path.startsWith("file://")) {
return new URL(null, path);
} else {
URL url;
try {
url = Classes.getResource(path, WSDLUtil.class);
} catch (IOException ioe) {
url = null;
}
if (url == null) {
File localFile = new File(path);
url = localFile.toURI().toURL();
}
return url;
}
}
/**
* Get the Service from the WSDL given a PortName.
* If the PortName.getServiceQName() is empty (QName("")) then this method returns the first found Service.
*
* @param wsdlLocation location pointing to a WSDL XML definition.
* @param portName the PortName.
* @return the Service.
* @throws WSDLException If the Service could not be retrieved.
*/
public static Service getService(final String wsdlLocation, final PortName portName) throws WSDLException {
Definition definition = readWSDL(wsdlLocation);
return getService(definition, portName);
}
/**
* Get the Service from the WSDL Definition given a PortName.
* If the PortName.getServiceQName() is empty (QName("")) then this method returns the first found Service.
*
* @param definition the WSDL XML definition.
* @param portName the PortName.
* @return the Service.
* @throws WSDLException If the Service could not be retrieved.
*/
public static Service getService(final Definition definition, final PortName portName) throws WSDLException {
Service service = null;
if (portName.getServiceQName().equals(new QName(""))) {
boolean found = false;
Iterator it_services = definition.getAllServices().values().iterator();
if (it_services != null) {
while (it_services.hasNext() && !found) {
service = (Service)it_services.next();
if (portName.getName() != null) {
if (service.getPort(portName.getName()) != null) {
portName.setServiceQName(service.getQName());
found = true;
} else {
service = null;
}
} else {
portName.setServiceQName(service.getQName());
found = true;
}
}
}
} else {
String namespace = portName.getNamespaceURI();
Boolean namespaceSet = false;
if (namespace.equals(XMLConstants.NULL_NS_URI)) {
namespace = definition.getTargetNamespace();
} else {
namespaceSet = true;
}
QName serviceQName = new QName(namespace, portName.getServiceName());
Iterator services = definition.getAllServices().values().iterator();
outer: while (services.hasNext()) {
Service wsdlService = services.next();
if (wsdlService.getQName().equals(serviceQName)) {
service = wsdlService;
break;
} else if (!namespaceSet) {
Iterator importedNamespaces = definition.getImports().keySet().iterator();
while (importedNamespaces.hasNext()) {
QName qName = new QName(importedNamespaces.next(), portName.getServiceName());
if (wsdlService.getQName().equals(qName)) {
service = wsdlService;
break outer;
}
}
}
}
}
if (service == null) {
throw new WSDLException(SOAPMessages.MESSAGES.couldNotFindServiceInTheWSDL(portName.toString(), definition.getDocumentBaseURI()), null);
}
return service;
}
/**
* Get the Port from the Service given a port name string. If the PortName.getName() is null then this method returns the first found Port.
*
* @param wsdlService the Service to be queried for.
* @param portName the PortName.
* @return the Webservice Port.
* @throws WSDLException If the Port could not be found.
*/
public static Port getPort(final Service wsdlService, final PortName portName) throws WSDLException {
String name = portName.getName();
Port port = null;
if ((name == null) || (name.length() == 0)) {
try {
port = (Port) wsdlService.getPorts().values().iterator().next();
} catch (NoSuchElementException nsee) {
throw new WSDLException(SOAPMessages.MESSAGES.couldNotFindAPortDefinitionWithinService(wsdlService.getQName().toString()), null);
}
} else {
Iterator ports = wsdlService.getPorts().values().iterator();
while (ports.hasNext()) {
Port wsdlPort = ports.next();
if (wsdlPort.getName().equals(name)) {
port = wsdlPort;
break;
}
}
}
if (port == null) {
throw new WSDLException(SOAPMessages.MESSAGES.couldNotFindPortInTheService(portName.toString(), wsdlService.getQName().toString()), null);
}
return port;
}
/**
* Get the style for the port binding.
* @param port The WSDL port.
* @return The style, can be 'document' or 'rpc'.
*/
@SuppressWarnings("unchecked")
public static String getStyle(Port port) {
String portStyle = null;
String bindingStyle = null;
for (ExtensibilityElement element : (List) port.getBinding().getExtensibilityElements()) {
if ((element instanceof SOAPBinding) && (((SOAPBinding)element).getStyle() != null)) {
bindingStyle = ((SOAPBinding) element).getStyle();
} else if ((element instanceof SOAP12Binding) && (((SOAP12Binding)element).getStyle() != null)) {
bindingStyle = ((SOAP12Binding) element).getStyle();
}
if (bindingStyle != null) {
portStyle = bindingStyle.toLowerCase();
}
}
String operationStyle = null;
String currentOperationStyle = null;
for (BindingOperation operation : (List) port.getBinding().getBindingOperations()) {
for (ExtensibilityElement element : (List) operation.getExtensibilityElements()) {
if (element instanceof SOAPOperation) {
currentOperationStyle = ((SOAPOperation) element).getStyle();
} else if (element instanceof SOAP12Operation) {
currentOperationStyle = ((SOAP12Operation) element).getStyle();
}
if (currentOperationStyle != null) {
if (operationStyle != null && !currentOperationStyle.equals(operationStyle)) {
throw SOAPMessages.MESSAGES.incompatibleStyleOfSoapOperationLevelBindingsDetected();
}
operationStyle = currentOperationStyle;
}
}
}
if (operationStyle != null && portStyle != null) {
if (!portStyle.equals(operationStyle)) {
throw SOAPMessages.MESSAGES.detectedMixingDifferentSoapBindingStyleOnPortTypeAndOperationLevel();
}
return portStyle;
} else if (portStyle != null) {
return portStyle;
} else if (operationStyle != null) {
return operationStyle;
}
return DOCUMENT; //default
}
/**
* Get the SOAP {@link Operation} instance for the specified message element.
*
* @param port The WSDL port.
* @param elementName The SOAP Body element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return The Operation instance, or null if the operation was not found on the port.
*/
public static Operation getOperationByElement(Port port, QName elementName, Boolean documentStyle) {
List operations = port.getBinding().getPortType().getOperations();
for (Operation operation : operations) {
if (!documentStyle && (elementName.getLocalPart().equals(operation.getName()))) {
return operation;
} else {
// Note: WS-I Profile allows only one child under SOAPBody.
Part part = (Part)operation.getInput().getMessage().getParts().values().iterator().next();
if ((part.getElementName() != null) && elementName.equals(part.getElementName())
|| (part.getTypeName() != null) && elementName.equals(part.getTypeName())) {
return operation;
} else if (elementName.getLocalPart().equals(operation.getName())) {
return operation;
}
}
}
return null;
}
/**
* Get the {@link Operation} instance for the specified SOAP operation name.
* @param port The WSDL port.
* @param operationName The SOAP Body element name.
* @return The Operation instance, or null if the operation was not found on the port.
*/
public static Operation getOperationByName(Port port, String operationName) {
Operation operation = null;
List operationList = port.getBinding().getPortType().getOperations();
for (Operation op : operationList) {
if (op.getName().equals(operationName)) {
operation = op;
break;
}
}
return operation;
}
/**
* Get the SOAP Binding Id for the specified {@link Port}.
*
* @param port The WSDL port.
* @param mtomEnabled MTOM feature boolean
* @return The SOAPBinding Id found on the port.
*/
public static String getBindingId(Port port, Boolean mtomEnabled) {
String bindingId = null;
List extElements = port.getExtensibilityElements();
for (ExtensibilityElement extElement : extElements) {
if (extElement instanceof SOAP12Address) {
if (mtomEnabled) {
bindingId = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING;
} else {
bindingId = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING;
}
break;
} else {
if (mtomEnabled) {
bindingId = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING;
} else {
bindingId = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
}
break;
}
}
return bindingId;
}
/**
* Get the SOAP Binding Id for the specified {@link Port}.
*
* @param port The WSDL port.
* @return The endpoint address.
*/
public static String getEndpointAddress(Port port) {
String address = null;
List extElements = port.getExtensibilityElements();
for (ExtensibilityElement extElement : extElements) {
if (extElement instanceof SOAPAddress) {
address = ((SOAPAddress)extElement).getLocationURI();
break;
} else if (extElement instanceof SOAP12Address) {
address = ((SOAP12Address)extElement).getLocationURI();
break;
}
}
return address;
}
/**
* Check if we are invoking a @Oneway annotated method.
*
* @param port The WSDL service port.
* @param elementName The SOAP Body element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return True if there is no response to be expected.
*/
public static boolean isOneWay(final Port port, final QName elementName, Boolean documentStyle) {
// Overloaded methods not supported
// Encrypted messages will be treated as request-response as it cannot be decrypted
Operation operation = getOperationByElement(port, elementName, documentStyle);
return isOneWay(operation);
}
/**
* Check if we are invoking a @Oneway annotated method.
*
* @param operation The WSDL Operation.
* @return True if there is no response to be expected.
*/
public static boolean isOneWay(final Operation operation) {
boolean isOneWay = false;
if (operation != null) {
isOneWay = operation.getStyle().equals(OperationType.ONE_WAY);
}
return isOneWay;
}
/**
* Get the SOAP {@link BindingOperation} instance for the specified SOAP operation name.
* @param port The WSDL port.
* @param elementName The SOAP Body element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return The BindingOperation instance, or null if the operation was not found on the port.
*/
public static BindingOperation getBindingOperation(Port port, QName elementName, Boolean documentStyle) {
Operation operation = getOperationByElement(port, elementName, documentStyle);
if (operation != null) {
List bindingOperations = port.getBinding().getBindingOperations();
for (BindingOperation bindingOperation : bindingOperations) {
if (bindingOperation.getName().equals(operation.getName())) {
return bindingOperation;
}
}
}
return null;
}
/**
* Get the soapAction value for a given operation.
*
* @param port The WSDL service port.
* @param elementName The SOAP Body element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return the soapAction value if it exists.
*/
public static String getSoapAction(final Port port, final QName elementName, Boolean documentStyle) {
// Overloaded methods not supported
BindingOperation operation = getBindingOperation(port, elementName, documentStyle);
return getSoapAction(operation);
}
/**
* Get the soapAction value for a given operation.
*
* @param operation The WSDL BindingOperation.
* @return the soapAction value if it exists.
*/
public static String getSoapAction(final BindingOperation operation) {
String soapActionUri = "";
if (operation != null) {
List extElements = operation.getExtensibilityElements();
for (ExtensibilityElement extElement : extElements) {
if (extElement instanceof SOAPOperation) {
soapActionUri = ((SOAPOperation) extElement).getSoapActionURI();
break;
} else if (extElement instanceof SOAP12Operation) {
SOAP12Operation soapOperation = ((SOAP12Operation) extElement);
Boolean soapActionRequired = soapOperation.getSoapActionRequired();
if ((soapActionRequired == null) || soapActionRequired) {
soapActionUri = soapOperation.getSoapActionURI();
}
break;
}
}
}
return soapActionUri;
}
/**
* Get the input action value for a given operation.
*
* @param port The WSDL service port.
* @param operationName The SOAP Operation element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return the input action value.
*/
public static String getInputAction(final Port port, final QName operationName, Boolean documentStyle) {
// Overloaded methods not supported
Operation operation = getOperationByElement(port, operationName, documentStyle);
String action = null;
String targetNamespace = operationName.getNamespaceURI();
for (QName attribute : (Set)operation.getInput().getExtensionAttributes().keySet()) {
if (attribute.equals(WSDL_ACTION_QNAME)) {
Object value = operation.getInput().getExtensionAttribute(WSDL_ACTION_QNAME);
if (value != null) {
action = ((QName)value).getLocalPart();
break;
}
}
}
if (action == null) {
// http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#defactionwsdl11
// [target namespace][delimiter][port type name][delimiter][input name]
String delimiter = targetNamespace.startsWith(SCHEME_URN) ? STR_COLON : STR_SLASH;
String namespace = targetNamespace.endsWith(delimiter) ? targetNamespace.substring(0, targetNamespace.length()-2) : targetNamespace;
if (operation.getInput().getName() != null) {
action = namespace + delimiter + port.getBinding().getPortType().getQName().getLocalPart() + delimiter + operation.getInput().getName();
} else {
action = namespace + delimiter + port.getBinding().getPortType().getQName().getLocalPart() + delimiter + operation.getName() + REQUEST_SUFFIX;
}
}
return action;
}
/**
* Get the output action value for a given operation.
*
* @param port The WSDL service port.
* @param operationName The SOAP Operation element QName.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return the output action value.
*/
public static String getOutputAction(final Port port, final QName operationName, Boolean documentStyle) {
// Overloaded methods not supported
Operation operation = getOperationByElement(port, operationName, documentStyle);
String action = null;
String targetNamespace = operationName.getNamespaceURI();
for (QName attribute : (Set)operation.getOutput().getExtensionAttributes().keySet()) {
if (attribute.equals(WSDL_ACTION_QNAME)) {
Object value = operation.getOutput().getExtensionAttribute(WSDL_ACTION_QNAME);
if (value != null) {
action = ((QName)value).getLocalPart();
break;
}
}
}
if (action == null) {
// http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#defactionwsdl11
// [target namespace][delimiter][port type name][delimiter][output name]
String delimiter = targetNamespace.startsWith(SCHEME_URN) ? STR_COLON : STR_SLASH;
String namespace = targetNamespace.endsWith(delimiter) ? targetNamespace.substring(0, targetNamespace.length()-2) : targetNamespace;
if (operation.getOutput().getName() != null) {
action = namespace + delimiter + port.getBinding().getPortType().getQName().getLocalPart() + delimiter + operation.getOutput().getName();
} else {
action = namespace + delimiter + port.getBinding().getPortType().getQName().getLocalPart() + delimiter + operation.getName() + RESPONSE_SUFFIX;
}
}
return action;
}
/**
* Get the fault action value for a given operation.
*
* @param port The WSDL service port.
* @param operationName The SOAP Operation element QName.
* @param faultName The fault name.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return the fault action value.
*/
public static String getFaultAction(final Port port, final QName operationName, String faultName, Boolean documentStyle) {
// Overloaded methods not supported
Operation operation = getOperationByElement(port, operationName, documentStyle);
if (operation.getFault(faultName) == null) {
throw SOAPMessages.MESSAGES.faultNameNotFoundOnOperation(faultName, operationName.getLocalPart());
}
return getFaultAction(operation.getFault(faultName), port, operationName);
}
/**
* Get the fault action value for a given operation.
*
* @param fault The WSDL Fault.
* @param port The WSDL service port.
* @param operationName The SOAP Operation element QName.
* @return the fault action value.
*/
public static String getFaultAction(final Fault fault, final Port port, final QName operationName) {
String action = null;
String targetNamespace = operationName.getNamespaceURI();
Object value = fault.getExtensionAttribute(WSDL_ACTION_QNAME);
if (value != null) {
action = ((QName)value).getLocalPart();
}
if (action == null) {
// http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#defactionwsdl11
// [target namespace][delimiter][port type name][delimiter][operation name][delimiter]Fault[delimiter][fault name]
String delimiter = targetNamespace.startsWith(SCHEME_URN) ? STR_COLON : STR_SLASH;
String namespace = targetNamespace.endsWith(delimiter) ? targetNamespace.substring(0, targetNamespace.length()-2) : targetNamespace;
action = namespace + delimiter + port.getBinding().getPortType().getQName().getLocalPart() + delimiter
+ operationName.getLocalPart() + delimiter + STR_FAULT + delimiter + fault.getName();
}
return action;
}
/**
* Get the fault QName.
*
* @param operation The WSDL operation.
* @param faultName the name of the Fault
* @return the fault QName or null.
*/
public static QName getFaultQName(final Operation operation, final String faultName) {
Fault fault = operation.getFault(faultName);
QName qName = null;
if (fault != null) {
qName = fault.getMessage().getQName();
}
return qName;
}
/**
* Get enabled features.
*
* @param definition The WSDL definition.
* @param port The WSDL service port.
* @param documentStyle true if it is 'document', false if 'rpc'.
* @return the feature booleans.
*/
public static Feature getFeature(final Definition definition, final Port port, Boolean documentStyle) {
Feature feature = new Feature();
Boolean addressing = false;
Boolean mtom = false;
List extensibilityElements = getExtensibilityElements(definition);
if (documentStyle) {
// Check if any element uses xmime:expectedContentTypes
for (ExtensibilityElement element : extensibilityElements) {
if (element instanceof Schema) {
mtom = setMtomEnabled((Schema)element);
if (mtom) {
feature.setMtomEnabled(true);
break;
}
}
}
} else {
// Check if any part uses xmime:expectedContentTypes
for (Message message : ((Map)definition.getMessages()).values()) {
for (Part part : (List)message.getOrderedParts(null)) {
if (part.getExtensionAttribute(MTOM_EXPT_QNAME) != null) {
feature.setMtomEnabled(true);
}
}
}
}
outer: for (ExtensibilityElement element : (List)port.getBinding().getExtensibilityElements()) {
if (element instanceof UnknownExtensibilityElement) {
String attrValue = null;
Element domElement = ((UnknownExtensibilityElement)element).getElement();
if (element.getElementType().equals(USING_WSA_QNAME)) {
feature.setAddressingEnabled(true);
setAddressingRequired(feature, domElement);
break;
} else if (element.getElementType().equals(POLICY_REFERENCE_QNAME)) {
String uri = XMLHelper.getAttribute(domElement, WSDL11_URI, ATTR_URI);
/*if (uri == null) {
uri = XMLHelper.getAttribute(domElement, WSDL20_URI, ATTR_URI);
}*/
if (uri == null) {
throw SOAPMessages.MESSAGES.policyReferenceURIMissingFor(port.getBinding().getQName().getLocalPart());
}
uri = uri.substring(1);
for (ExtensibilityElement defElement : extensibilityElements) {
if (defElement.getElementType().equals(POLICY_QNAME)) {
Element defDomElement = ((UnknownExtensibilityElement)defElement).getElement();
attrValue = XMLHelper.getAttribute(defDomElement, SECURITY_UTILITY_URI, ATTR_ID);
if ((attrValue != null)
&& attrValue.equals(uri)) {
// Addressing
if (!addressing) {
addressing = setAddressingEnabled(feature, defDomElement);
}
// MTOM
if (!mtom) {
mtom = setMtomEnabled(feature, defDomElement);
}
if (addressing && mtom) {
break outer;
}
}
}
}
}
}
}
return feature;
}
private static List getExtensibilityElements(Definition definition) {
List elements = new ArrayList();
Types types = definition.getTypes();
if (types != null) {
elements.addAll(definition.getExtensibilityElements());
elements.addAll(types.getExtensibilityElements());
}
Iterator> wsdlImports = definition.getImports().values().iterator();
while (wsdlImports.hasNext()) {
List imports = wsdlImports.next();
int size = imports.size();
for (int i = 0; i < size; i++) {
elements.addAll(getExtensibilityElements(imports.get(i).getDefinition()));
}
}
return elements;
}
private static Boolean setAddressingEnabled(Feature feature, Element defDomElement) {
Element child = XMLHelper.getFirstChildElementByName(defDomElement, ELE_ADDRESSING);
if (child != null) {
feature.setAddressingEnabled(true);
setAddressingRequired(feature, child);
return true;
} else {
child = XMLHelper.getFirstChildElementByName(defDomElement, ELE_EXACTLYONE);
if (child != null) {
child = XMLHelper.getFirstChildElementByName(child, ELE_ALL);
while (child != null) {
Element addressingEle = XMLHelper.getFirstChildElementByName(child, ELE_ADDRESSING);
if (addressingEle != null) {
feature.setAddressingEnabled(true);
setAddressingRequired(feature, addressingEle);
return true;
}
child = XMLHelper.getNextSiblingElementByName(child, ELE_ALL);
}
}
}
return false;
}
private static void setAddressingRequired(Feature feature, Element element) {
String attrValue = XMLHelper.getAttribute(element, WSDL11_URI, ATTR_REQUIRED);
/*if (attrValue == null) {
attrValue = XMLHelper.getAttribute(element, WSDL20_URI, ATTR_REQUIRED);
}*/
if (attrValue != null) {
feature.setAddressingRequired(Boolean.valueOf(attrValue));
}
}
private static Boolean setMtomEnabled(Feature feature, Element defDomElement) {
Element child = XMLHelper.getFirstChildElementByName(defDomElement, ELE_MTOM);
if (child != null) {
feature.setMtomEnabled(true);
return true;
} else {
child = XMLHelper.getFirstChildElementByName(defDomElement, ELE_EXACTLYONE);
if (child != null) {
child = XMLHelper.getFirstChildElementByName(child, ELE_ALL);
while (child != null) {
Element addressingEle = XMLHelper.getFirstChildElementByName(child, ELE_MTOM);
if (addressingEle != null) {
feature.setMtomEnabled(true);
return true;
}
child = XMLHelper.getNextSiblingElementByName(child, ELE_ALL);
}
}
}
return false;
}
// Caution: recursive
private static Boolean setMtomEnabled(Schema schema) {
if (schema != null) {
if (hasExpectedContentTypes(schema.getElement())) {
return true;
}
for (List c : ((Map>)schema.getImports()).values()) {
for (SchemaImport simport : c) {
if (setMtomEnabled(simport.getReferencedSchema())) {
return true;
}
}
}
}
return false;
}
// Caution: recursive
private static Boolean hasExpectedContentTypes(Element element) {
if (element != null) {
if (XMLHelper.hasAttribute(element, WSDL_XMIME_URI, ATTR_EXP_CT)) {
return true;
}
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (hasExpectedContentTypes((Element)node)) {
return true;
}
}
}
}
return false;
}
/**
* Given a Port construct the Exchange Contracts for all Operations.
*
* @param port The WSDL service port.
* @param service The SwitchYard service.
* @return A Map of exchange contracts.
* @throws WebServicePublishException If the WSDL does not match the Service operations.
public static Map getContracts(final Port port, final org.switchyard.ServiceReference service) throws WebServicePublishException {
Map contracts = new HashMap();
List operations = port.getBinding().getPortType().getOperations();
if ((operations == null) || operations.isEmpty()) {
throw SOAPMessages.MESSAGES.invalidWSDLNoOperationsFound();
}
for (Operation operation : operations) {
String name = operation.getName();
ServiceOperation targetServiceOperation = service.getInterface().getOperation(name);
if (targetServiceOperation == null) {
throw SOAPMessages.MESSAGES.wSDLOperationNotFoundInService(name, service.getName());
}
ExchangePattern wsdlExchangePattern = getExchangePattern(operation);
if (targetServiceOperation.getExchangePattern() != wsdlExchangePattern) {
throw SOAPMessages.MESSAGES.wSDLOperationDoesNotMatchServiceOperation(name, targetServiceOperation.getName());
}
BaseExchangeContract exchangeContract = new BaseExchangeContract(targetServiceOperation);
BaseInvocationContract soapMetaData = exchangeContract.getInvokerInvocationMetaData();
List parts = operation.getInput().getMessage().getOrderedParts(null);
if (parts.isEmpty()) {
throw SOAPMessages.MESSAGES.wSDLOperationDoesNotHaveAnyInputMessageParts(name);
}
// Only one Part (one child of the soap:body) allowed per WS-I Basic Profile similar to Document/Literal wrapped
QName inputMessageQName = parts.get(0).getElementName();
soapMetaData.setInputType(inputMessageQName);
soapMetaData.setFaultType(SOAP_FAULT_MESSAGE_TYPE);
if (!isOneWay(operation)) {
parts = operation.getOutput().getMessage().getOrderedParts(null);
if (parts.isEmpty()) {
throw SOAPMessages.MESSAGES.wSDLOperationDoesNotHaveAnyOuputMessageParts(name);
}
// Only one Part (one child of the soap:body) allowed per WS-I Basic Profile similar to Document/Literal wrapped
QName outputMessageQName = parts.get(0).getElementName();
soapMetaData.setOutputType(outputMessageQName);
}
contracts.put(name, exchangeContract);
}
return contracts;
}
*/
/**
* Get the exchange pattern for the specified WS Operation.
*
* @param operation The operation to check for.
* @return The Exchange Pattern.
*/
public static ExchangePattern getExchangePattern(final Operation operation) {
if (operation.getStyle().equals(OperationType.ONE_WAY)) {
return ExchangePattern.IN_ONLY;
} else {
return ExchangePattern.IN_OUT;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy