org.switchyard.component.soap.util.WSDLUtil Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
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.Iterator;
import java.util.List;
import javax.wsdl.Definition;
import javax.wsdl.Operation;
import javax.wsdl.OperationType;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.WSDLException;
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.apache.log4j.Logger;
import org.switchyard.ExchangePattern;
import org.switchyard.common.type.Classes;
import org.switchyard.common.xml.XMLHelper;
import org.switchyard.component.soap.PortName;
import org.w3c.dom.Document;
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);
/**
* SOAP Fault type QName.
*/
public static final QName SOAP_FAULT_MESSAGE_TYPE =
QName.valueOf("{http://schemas.xmlsoap.org/soap/envelope/}Fault");
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,
"Unable to read WSDL at '"
+ 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,
"Unable to resolve WSDL document at '"
+ wsdlURI, 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);
Service service = null;
if (portName.getServiceQName().equals(new QName(""))) {
service = (Service) definition.getServices().values().iterator().next();
portName.setServiceQName(service.getQName());
} else {
String namespace = portName.getNamespaceURI();
if (namespace.equals(XMLConstants.NULL_NS_URI)) {
namespace = definition.getTargetNamespace();
}
QName serviceQName = new QName(namespace, portName.getServiceName());
Iterator services = definition.getServices().values().iterator();
while (services.hasNext()) {
Service wsdlService = services.next();
if (wsdlService.getQName().equals(serviceQName)) {
service = wsdlService;
break;
}
}
}
if (service == null) {
throw new WSDLException("Could not find service " + portName + " in the WSDL " + wsdlLocation, 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)) {
port = (Port) wsdlService.getPorts().values().iterator().next();
} 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("Could not find port " + portName + " in the Service " + wsdlService.getQName(), null);
}
return port;
}
/**
* Get the SOAP {@link Operation} instance for the specified SOAP operation name.
* @param port The WSDL port.
* @param elementName The SOAP Body element name.
* @return The Operation instance, or null if the operation was not found on the port.
*/
public static Operation getOperation(Port port, String elementName) {
List operations = port.getBinding().getPortType().getOperations();
for (Operation operation : operations) {
Part part = (Part)operation.getInput().getMessage().getParts().values().iterator().next();
if (elementName.equals(part.getElementName().getLocalPart())) {
return operation;
}
}
return null;
}
/**
* Check if we are invoking a @Oneway annotated method.
*
* @param port The WSDL service port.
* @param elementName The SOAP Body element name.
* @return True if there is no response to be expected.
*/
public static boolean isOneWay(final Port port, final String elementName) {
// Overloaded methods not supported
// Encrypted messages will be treated as request-response as it cannot be decrypted
Operation operation = getOperation(port, elementName);
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 methods Input message's name.
*
* @param port The WSDL service port.
* @param operationName The name of the operation obtained from SOAP message.
* @return The local name of the input message.
*/
public static String getMessageLocalName(final Port port, final String operationName) {
QName messageName = getMessageQName(port, operationName);
if (messageName != null) {
return messageName.getLocalPart();
}
return null;
}
/**
* Get the methods Input message's name.
*
* @param port The WSDL service port.
* @param operationName The name of the operation obtained from SOAP message.
* @return The QName name of the input message.
*/
public static QName getMessageQName(final Port port, final String operationName) {
QName messageName = null;
// Overloaded methods not supported
// Encrypted messages will be treated as request-response as it cannot be decrypted
Operation operation = getOperation(port, operationName);
if (operation != null) {
messageName = operation.getInput().getMessage().getQName();
}
return messageName;
}
/**
* 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 new WebServicePublishException("Invalid WSDL. No operations found.");
}
for (Operation operation : operations) {
String name = operation.getName();
ServiceOperation targetServiceOperation = service.getInterface().getOperation(name);
if (targetServiceOperation == null) {
throw new WebServicePublishException("WSDL Operation " + name + " not found in Service " + service.getName());
}
ExchangePattern wsdlExchangePattern = getExchangePattern(operation);
if (targetServiceOperation.getExchangePattern() != wsdlExchangePattern) {
throw new WebServicePublishException("WSDL Operation " + name + " does not match Service Operation " + targetServiceOperation.getName());
}
BaseExchangeContract exchangeContract = new BaseExchangeContract(targetServiceOperation);
BaseInvocationContract soapMetaData = exchangeContract.getInvokerInvocationMetaData();
List parts = operation.getInput().getMessage().getOrderedParts(null);
if (parts.isEmpty()) {
throw new WebServicePublishException("WSDL Operation " + name + " does not have any input Message parts");
}
// 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 new WebServicePublishException("WSDL Operation " + name + " does not have any ouput Message parts");
}
// 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