/** | |
* ***************************************************************************** | |
* Copyright (C) 2012 Spanish National Bioinformatics Institute (INB), | |
* Barcelona Supercomputing Center and The University of Manchester | |
* | |
* Modifications to the initial code base are copyright of their respective | |
* authors, or their employers as appropriate. | |
* | |
* This program 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 program 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 program; if not, write to the Free Software Foundation, Inc., | |
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
***************************************************************************** | |
*/ | |
package net.sf.taverna.wsdl.parser; | |
import java.io.IOException; | |
import java.io.StringWriter; | |
import java.io.Writer; | |
import java.net.URI; | |
import java.util.ArrayList; | |
import java.util.LinkedHashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.TreeMap; | |
import javax.xml.namespace.QName; | |
import javax.xml.transform.Transformer; | |
import javax.xml.transform.TransformerConfigurationException; | |
import javax.xml.transform.TransformerException; | |
import javax.xml.transform.TransformerFactory; | |
import javax.xml.transform.TransformerFactoryConfigurationError; | |
import javax.xml.transform.dom.DOMSource; | |
import javax.xml.transform.stream.StreamResult; | |
import org.apache.woden.WSDLFactory; | |
import org.apache.woden.WSDLReader; | |
import org.apache.woden.XMLElement; | |
import org.apache.woden.types.NCName; | |
import org.apache.woden.wsdl20.Binding; | |
import org.apache.woden.wsdl20.BindingOperation; | |
import org.apache.woden.wsdl20.Description; | |
import org.apache.woden.wsdl20.ElementDeclaration; | |
import org.apache.woden.wsdl20.Endpoint; | |
import org.apache.woden.wsdl20.Interface; | |
import org.apache.woden.wsdl20.InterfaceMessageReference; | |
import org.apache.woden.wsdl20.InterfaceOperation; | |
import org.apache.woden.wsdl20.Service; | |
import org.apache.woden.wsdl20.enumeration.Direction; | |
import org.apache.woden.wsdl20.extensions.ExtensionProperty; | |
import org.apache.woden.wsdl20.extensions.soap.SOAPConstants; | |
import org.apache.woden.wsdl20.xml.DescriptionElement; | |
import org.apache.woden.wsdl20.xml.DocumentationElement; | |
import org.apache.ws.commons.schema.XmlSchemaCollection; | |
import org.apache.ws.commons.schema.XmlSchemaObject; | |
import org.w3c.dom.Element; | |
/** | |
* @author Dmitry Repchevsky | |
*/ | |
public class WSDL20Parser implements GenericWSDLParser { | |
private static Map<String, WSDL20Parser> parsers; | |
private final Description description; | |
private final XmlSchemaCollection schemas; | |
private WSDL20Parser(Description description) throws IOException { | |
this.description = description; | |
schemas = new XmlSchemaCollection(); | |
} | |
@Override | |
public String getDocumentBaseURI() { | |
DescriptionElement element = description.toElement(); | |
URI documentBaseURI = element.getDocumentBaseURI(); | |
return documentBaseURI == null ? null : documentBaseURI.toString(); | |
} | |
@Override | |
public List<QName> getServices() { | |
List<QName> services = new ArrayList<QName>(); | |
for (Service service : description.getServices()) { | |
services.add(service.getName()); | |
} | |
return services; | |
} | |
@Override | |
public List<String> getPorts(QName serviceName) { | |
List<String> ports = new ArrayList<String>(); | |
Service service = description.getService(serviceName); | |
if (service != null) { | |
for (Endpoint endpoint : service.getEndpoints()) { | |
final NCName endpointName = endpoint.getName(); | |
if (endpointName != null) { | |
ports.add(endpointName.toString()); | |
} | |
} | |
} | |
return ports; | |
} | |
@Override | |
public List<String> getOperations(String portName) { | |
List<String> operations = new ArrayList<String>(); | |
for (Service service : description.getServices()) { | |
for (Endpoint endpoint : service.getEndpoints()) { | |
final NCName endpointName = endpoint.getName(); | |
if (endpointName != null && endpointName.toString().equals(portName)) { | |
Binding binding = endpoint.getBinding(); | |
if (binding != null) { | |
for (BindingOperation bindingOperation : binding.getBindingOperations()) { | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
if (interfaceOperation != null) { | |
operations.add(interfaceOperation.getName().getLocalPart()); | |
} | |
} | |
} | |
} | |
} | |
} | |
return operations; | |
} | |
@Override | |
public WSRF_Version isWSRFPort(String portName) { | |
return null; | |
} | |
@Override | |
public String getOperationStyle(String portName, String operationName) throws UnknownOperationException { | |
return "document"; | |
} | |
@Override | |
public String getSOAPActionURI(String portName, String operationName) throws UnknownOperationException { | |
BindingOperation bindingOperation = getBindingOperation(portName, operationName); | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
ExtensionProperty property = interfaceOperation.getExtensionProperty(SOAPConstants.NS_URI_SOAP, SOAPConstants.ATTR_ACTION); | |
return property == null ? null : property.getContent().toString(); | |
} | |
@Override | |
public QName getRPCRequestMethodName(String portName, String operationName) throws UnknownOperationException { | |
// NO RPC SUPPORT YET | |
return new QName(operationName); | |
} | |
@Override | |
public QName getRPCResponseMethodName(String portName, String operationName) throws UnknownOperationException { | |
// NO RPC SUPPORT YET | |
return new QName(operationName); | |
} | |
@Override | |
public String getSoapInputUse(String portName, String operationName) throws UnknownOperationException { | |
return "literal"; | |
} | |
@Override | |
public String getSoapOutputUse(String portName, String operationName) throws UnknownOperationException { | |
return "literal"; | |
} | |
@Override | |
public String getSoapAddress(String portName) { | |
for (Service service : description.getServices()) { | |
for (Endpoint endpoint : service.getEndpoints()) { | |
final NCName endpointName = endpoint.getName(); | |
if (endpointName != null && endpointName.toString().equals(portName)) { | |
URI address = endpoint.getAddress(); | |
return address == null ? null : address.toString(); | |
} | |
} | |
} | |
return null; | |
} | |
@Override | |
public String getOperationEndpointLocation(String operationName) throws UnknownOperationException { | |
for (Service service : description.getServices()) { | |
for (Endpoint endpoint : service.getEndpoints()) { | |
Binding binding = endpoint.getBinding(); | |
if (binding != null) { | |
for (BindingOperation o : binding.getBindingOperations()) { | |
InterfaceOperation operation = o.getInterfaceOperation(); | |
if (operation != null && operationName.equals(operation.getName().getLocalPart())) { | |
URI address = endpoint.getAddress(); | |
return address == null ? null : address.toString(); | |
} | |
} | |
} | |
} | |
} | |
return null; | |
} | |
@Override | |
public String getOperationDocumentation(String portName, String operationName) throws UnknownOperationException { | |
Writer writer = new StringWriter(); | |
BindingOperation bindingOperation = getBindingOperation(portName, operationName); | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
try { | |
Transformer transformer = TransformerFactory.newInstance().newTransformer(); | |
for (DocumentationElement documentation : interfaceOperation.toElement().getDocumentationElements()) { | |
XMLElement xml = documentation.getContent(); | |
Object source = xml.getSource(); | |
if (source instanceof Element) { | |
Element element = (Element)source; | |
try { | |
transformer.transform(new DOMSource(element), new StreamResult(writer)); | |
} catch (TransformerException ex) {} | |
} | |
} | |
} catch (TransformerFactoryConfigurationError ex) {} | |
catch (TransformerConfigurationException ex) {} | |
return writer.toString(); | |
} | |
@Override | |
public LinkedHashMap<String, XmlSchemaObject> getInputParameters(String portName, String operationName) throws UnknownOperationException { | |
LinkedHashMap<String, XmlSchemaObject> parameters = new LinkedHashMap<String, XmlSchemaObject>(); | |
BindingOperation bindingOperation = getBindingOperation(portName, operationName); | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
// NOTE THAT THIS CODE IS NOT VALID FOR "RPC" STYLE | |
for (InterfaceMessageReference input : interfaceOperation.getInterfaceMessageReferences()) { | |
if (Direction.IN == input.getDirection()) { | |
ElementDeclaration element = input.getElementDeclaration(); | |
parameters.put(element.getName().getLocalPart(), (XmlSchemaObject)element.getContent()); | |
} | |
} | |
return parameters; | |
} | |
@Override | |
public LinkedHashMap<String, XmlSchemaObject> getOutputParameters(String portName, String operationName) throws UnknownOperationException { | |
LinkedHashMap<String, XmlSchemaObject> parameters = new LinkedHashMap<String, XmlSchemaObject>(); | |
BindingOperation bindingOperation = getBindingOperation(portName, operationName); | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
// NOTE THAT THIS CODE IS NOT VALID FOR "RPC" STYLE | |
for (InterfaceMessageReference output : interfaceOperation.getInterfaceMessageReferences()) { | |
if (Direction.OUT == output.getDirection()) { | |
ElementDeclaration element = output.getElementDeclaration(); | |
parameters.put(element.getName().getLocalPart(), (XmlSchemaObject)element.getContent()); | |
} | |
} | |
return parameters; | |
} | |
private BindingOperation getBindingOperation(String portName, String operationName) throws UnknownOperationException { | |
Binding[] bindings = null; | |
if (portName == null) { | |
bindings = description.getBindings(); | |
} else { | |
loop: | |
for (Service service : description.getServices()) { | |
for (Endpoint endpoint : service.getEndpoints()) { | |
final NCName endpointName = endpoint.getName(); | |
if (endpointName != null && endpointName.toString().equals(portName)) { | |
Binding binding = endpoint.getBinding(); | |
if (binding != null) { | |
bindings = new Binding[] {binding}; | |
break loop; | |
} | |
} | |
} | |
} | |
if (bindings == null) { | |
bindings = description.getBindings(); | |
} | |
} | |
if (bindings != null) { | |
for (Binding binding : bindings) { | |
for (BindingOperation bindingOperation : binding.getBindingOperations()) { | |
InterfaceOperation interfaceOperation = bindingOperation.getInterfaceOperation(); | |
if (interfaceOperation != null && operationName.equals(interfaceOperation.getName().getLocalPart())) { | |
return bindingOperation; | |
} | |
} | |
} | |
} | |
throw new UnknownOperationException("Unknown operation: " + operationName); | |
} | |
public static synchronized WSDL20Parser getWSDL20Parser(String wsdlLocation) throws Exception { | |
WSDL20Parser parser = null; | |
if (parsers == null) { | |
parsers = new TreeMap<String, WSDL20Parser>(); | |
} else { | |
parser = parsers.get(wsdlLocation); | |
} | |
if (parser == null) { | |
WSDLFactory factory = WSDLFactory.newInstance(); | |
WSDLReader reader = factory.newWSDLReader(); | |
reader.setFeature(WSDLReader.FEATURE_VALIDATION, true); | |
Description description = reader.readWSDL(wsdlLocation); | |
parser = new WSDL20Parser(description); | |
parsers.put(wsdlLocation, parser); | |
} | |
return parser; | |
} | |
} |