You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:16:54 UTC
[13/28] incubator-taverna-common-activities git commit: Revert
"temporarily empty repository"
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/LiteralBodyBuilder.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/LiteralBodyBuilder.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/LiteralBodyBuilder.java
new file mode 100644
index 0000000..274aa55
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/LiteralBodyBuilder.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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.soap;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.wsdl.WSDLException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPException;
+
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.BaseTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.parser.WSDLParser;
+
+import org.apache.axis.message.MessageElement;
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * An implementation of BodyBuilder that supports creating the SOAP body for
+ * Webservices based upon a WSDL with Literal style.
+ *
+ * @author Stuart Owen
+ * @author Stian Soiland-Reyes
+ *
+ */
+@SuppressWarnings("unchecked")
+public class LiteralBodyBuilder extends AbstractBodyBuilder {
+
+ private static Logger logger = Logger.getLogger(LiteralBodyBuilder.class);
+
+ private static final String TYPE = "type";
+ private static final String NS_XSI = "http://www.w3.org/2001/XMLSchema-instance";
+
+ public LiteralBodyBuilder(String style, WSDLParser parser, String operationName, List<TypeDescriptor> inputDescriptors) {
+ super(style, parser, operationName,inputDescriptors);
+ }
+
+ @Override
+ protected Use getUse() {
+ return Use.LITERAL;
+ }
+
+ @Override
+ public SOAPBodyElement build(Map inputMap) throws WSDLException,
+ ParserConfigurationException, SOAPException, IOException,
+ SAXException, UnknownOperationException {
+
+ SOAPBodyElement body = super.build(inputMap);
+
+ if (getStyle() == Style.DOCUMENT) {
+ fixTypeAttributes(body);
+ }
+
+ return body;
+ }
+
+ @Override
+ protected Element createSkeletonElementForSingleItem(
+ Map<String, String> namespaceMappings, TypeDescriptor descriptor,
+ String inputName, String typeName) {
+ if (getStyle()==Style.DOCUMENT) {
+ return XMLUtils.StringToElement("", descriptor.getQname().getLocalPart(), "");
+ }
+ else {
+ return XMLUtils.StringToElement("", inputName, "");
+ }
+ }
+
+ private void fixTypeAttributes(Node parent) {
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ Element el = (Element) parent;
+ if (parent.hasAttributes()) {
+ NamedNodeMap attributes = parent.getAttributes();
+// List<Node> attributeNodesForRemoval = new ArrayList<Node>();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Node node = attributes.item(i);
+
+ if (NS_XSI.equals(node.getNamespaceURI()) && TYPE.equals(node.getLocalName())) {
+ // TAV-712 - don't just strip out xsi:type - let's fix the
+ // name prefixes instead
+
+ String xsiType = node.getTextContent();
+ // Resolve prefix of xsi type
+ String[] xsiTypeSplitted = xsiType.split(":", 2);
+ String xsiTypePrefix = "";
+ String xsiTypeName;
+ if (xsiTypeSplitted.length == 1) {
+ // No prefix
+ xsiTypeName = xsiTypeSplitted[0];
+ } else {
+ xsiTypePrefix = xsiTypeSplitted[0];
+ xsiTypeName = xsiTypeSplitted[1];
+ }
+
+ String xsiTypeNS;
+ if (parent instanceof MessageElement) {
+ xsiTypeNS = ((MessageElement)parent).getNamespaceURI(xsiTypePrefix);
+ } else {
+ xsiTypeNS = node
+ .lookupNamespaceURI(xsiTypePrefix);
+ }
+ // Use global namespace prefixes
+ String newPrefix = namespaceMappings.get(xsiTypeNS);
+ if (newPrefix == null) {
+ logger.warn("Can't find prefix for xsi:type namespace " + xsiTypeNS + " - keeping old " + xsiType);
+ } else {
+ String newXsiType = newPrefix + ":" + xsiTypeName;
+ node.setTextContent(newXsiType);
+ logger.info("Replacing " + xsiType + " with " + newXsiType);
+ }
+ }
+ }
+// for (Node node : attributeNodesForRemoval) {
+// el.removeAttributeNS(node.getNamespaceURI(), node
+// .getLocalName());
+// }
+ }
+ }
+
+ if (parent instanceof SOAPElement) {
+ for (Iterator childIterator = ((SOAPElement) parent).getChildElements(); childIterator.hasNext();) {
+ Node childElement = (Node) childIterator.next();
+ fixTypeAttributes(childElement);
+ }
+ }
+// final NodeList childNodes = parent.getChildNodes();
+// for (int i = 0; i < childNodes.getLength(); i++) {
+// fixTypeAttributes(childNodes.item(i));
+// }
+ }
+
+ @Override
+ protected Element createElementForArrayType(
+ Map<String, String> namespaceMappings, String inputName,
+ Object dataValue, TypeDescriptor descriptor, String mimeType,
+ String typeName) throws ParserConfigurationException, SAXException,
+ IOException, UnknownOperationException {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory
+ .newInstance();
+ builderFactory.setNamespaceAware(true);
+ DocumentBuilder docBuilder = builderFactory.newDocumentBuilder();
+
+ Element el;
+ ArrayTypeDescriptor arrayDescriptor = (ArrayTypeDescriptor) descriptor;
+ TypeDescriptor elementType = arrayDescriptor.getElementType();
+ int size = 0;
+
+ el = XMLUtils.StringToElement("", typeName, "");
+
+ if (dataValue instanceof List) {
+ List dataValues = (List) dataValue;
+ size = dataValues.size();
+ populateElementWithList(mimeType, el, dataValues, elementType);
+ } else {
+
+ // if mime type is text/xml then the data is an array in xml form,
+ // else its just a single primitive element
+ if (mimeType.equals("'text/xml'")) {
+
+ Document doc = docBuilder.parse(new ByteArrayInputStream(
+ dataValue.toString().getBytes()));
+ Node child = doc.getDocumentElement().getFirstChild();
+
+ while (child != null) {
+ size++;
+ el.appendChild(el.getOwnerDocument()
+ .importNode(child, true));
+ child = child.getNextSibling();
+ }
+ } else {
+ String tag = "item";
+ if (elementType instanceof BaseTypeDescriptor) {
+ tag = elementType.getType();
+ } else {
+ tag = elementType.getName();
+ }
+ Element item = el.getOwnerDocument().createElement(tag);
+ populateElementWithObjectData(mimeType, item, dataValue, descriptor);
+ el.appendChild(item);
+ }
+
+ }
+
+ return el;
+ }
+
+ @Override
+ protected SOAPBodyElement addElementToBody(String operationNamespace, SOAPBodyElement body, Element el) throws SOAPException {
+ if (getStyle()==Style.DOCUMENT) {
+ body = new SOAPBodyElement(el);
+ body.setNamespaceURI(operationNamespace);
+ }
+ else {
+ body.addChildElement(new SOAPBodyElement(el));
+ }
+ return body;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/ObjectConverter.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/ObjectConverter.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/ObjectConverter.java
new file mode 100644
index 0000000..f973157
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/ObjectConverter.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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.soap;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <p>
+ * This class replicates the behaviour of data conversion when using DataThingFactory.bake in Taverna 1.
+ * </p>
+ * <p>
+ * In particular it deals with the conversion of arrays to ArrayList
+ * </p>
+ * @author Stuart Owen
+ *
+ *
+ */
+public class ObjectConverter {
+
+ /**
+ * Converts an Object into an appropriate type, in particular recursively converting [] arrays to List<?>'s.<br>
+ *
+ * This method is a copy of convertObject in DataThingFactory from Taverna 1
+ * @param theObject
+ * @return
+ */
+ public static Object convertObject(Object theObject) {
+
+ if (theObject == null) {
+ return null;
+ }
+ // If an array type...
+ Class<?> theClass = theObject.getClass();
+ if (theClass.isArray()) {
+ // Special case for byte[]
+ if (theObject instanceof byte[]) {
+ // System.out.println("Found a byte[], returning it.");
+ return theObject;
+ } //extra primitive object checks for those fun edge cases!
+ else if (theObject instanceof int[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((int[])theObject).length;i++) {
+ Object a = ((int[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof short[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((short[])theObject).length;i++) {
+ Object a = ((short[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof long[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((long[])theObject).length;i++) {
+ Object a = ((long[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof float[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((float[])theObject).length;i++) {
+ Object a = ((float[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof double[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((double[])theObject).length;i++) {
+ Object a = ((double[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof boolean[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((boolean[])theObject).length;i++) {
+ Object a = ((boolean[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else if (theObject instanceof char[]){
+ List<Object> l = new ArrayList<Object>();
+ for (int i = 0; i<((char[])theObject).length;i++) {
+ Object a = ((char[])theObject)[i];
+ l.add(convertObject(a));
+ }
+ return l;
+ } else {
+ // For all other arrays, create a new
+ // List and iterate over the array,
+ // unpackaging the item and recursively
+ // putting it into the new List after
+ // conversion
+
+ // System.out.println("Found an array length
+ // "+theArray.length+", repacking as List...");
+
+ List<Object> l = new ArrayList<Object>();
+ Object[] theArray = (Object[]) theObject;
+ for (int i = 0; i < theArray.length; i++) {
+ l.add(convertObject(theArray[i]));
+ }
+ return l;
+ }
+ }
+ // If a collection, iterate over it and copy
+ if (theObject instanceof Collection) {
+ if (theObject instanceof List) {
+ // System.out.println("Re-packing a list...");
+ List<Object> l = new ArrayList<Object>();
+ for (Iterator<?> i = ((List<?>) theObject).iterator(); i.hasNext();) {
+ l.add(convertObject(i.next()));
+ }
+ return l;
+ } else if (theObject instanceof Set) {
+ // System.out.println("Re-packing a set...");
+ Set<Object> s = new HashSet<Object>();
+ for (Iterator<?> i = ((Set<?>) theObject).iterator(); i.hasNext();) {
+ s.add(convertObject(i.next()));
+ }
+ return s;
+ }
+ }
+ // If a number then return the string representation for it
+ if (theObject instanceof Number) {
+ // System.out.println("Found a number, converting it to a
+ // string...");
+ return theObject.toString();
+ }
+ // Otherwise just return the object
+ // System.out.println("Found a "+theObject.getClass().getName()+",
+ // returning it");
+ return theObject;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedMultiRefParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedMultiRefParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedMultiRefParser.java
new file mode 100644
index 0000000..2266e0d
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedMultiRefParser.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponseEncodedMultiRefParser.java,v $
+ * Revision $Revision: 1.2 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2008/08/08 10:28:09 $
+ * by $Author: stain $
+ * Created on 05-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * A SOAPResponseParser responsible for responses that are fragmented into
+ * seperate referenced blocks of XML - Multiref format. It trys to resolve each
+ * reference to the corresponding multiref element, eventually generating a
+ * single XML document. Cyclic references are not allows, and lead to a
+ * CyclicReferenceException
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponseEncodedMultiRefParser extends
+ SOAPResponseEncodedParser {
+
+ private List resolvedReferences = new ArrayList();
+
+ private Map referenceMap;
+
+ public SOAPResponseEncodedMultiRefParser(List<TypeDescriptor> outputDescriptors) {
+ super(outputDescriptors);
+ }
+
+ /**
+ * Expects a list of XML SOAPBodyElement fragements, with the first being
+ * the root, and transforms this into a single XML document. Cyclic
+ * references lead to a CyclicReferenceException being thrown. XML
+ * namespaces are removed, leading to easier to read XML.
+ *
+ * @param response -
+ * List of XML SOAPBodyElement fragments.
+ */
+ @Override
+ public Map parse(List response) throws Exception, CyclicReferenceException {
+ Map result = new HashMap();
+ generateRefMap(response);
+ expandRefMap();
+ Element mainBody = ((SOAPBodyElement) response.get(0)).getAsDOM();
+
+ for (TypeDescriptor descriptor : outputDescriptors) {
+ String outputName = descriptor.getName();
+
+ Node outputNode = getOutputNode(mainBody, outputName);
+ if (outputNode != null) {
+ expandNode(outputNode, new ArrayList());
+ String xml;
+ if (getStripAttributes()) {
+ stripAttributes(outputNode);
+ outputNode = removeNamespace(outputName,
+ (Element) outputNode);
+ }
+ xml = XMLUtils.ElementToString((Element) outputNode);
+
+ result.put(outputName, xml);
+ }
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Generates a map of each multiref element, mapped to its ID.
+ *
+ * @param response
+ * @throws Exception
+ */
+ private void generateRefMap(List response) throws Exception {
+ Map result = new HashMap();
+
+ for (Iterator iterator = response.iterator(); iterator.hasNext();) {
+ SOAPBodyElement bodyElement = (SOAPBodyElement) iterator.next();
+ String id = bodyElement.getAttribute("id");
+ if (id != null) {
+ result.put("#" + id, bodyElement.getAsDOM());
+ }
+ }
+
+ referenceMap = result;
+ }
+
+ /**
+ * Expands any references to other fragments within each multiref fragment,
+ * resulting in all multiref fragments being fully expanded.
+ *
+ * @throws CyclicReferenceException
+ */
+ private void expandRefMap() throws CyclicReferenceException {
+ for (Iterator iterator = referenceMap.keySet().iterator(); iterator
+ .hasNext();) {
+ String key = (String) iterator.next();
+ if (!resolvedReferences.contains(key)) {
+ expandMultirefElement(key, new ArrayList());
+ }
+ }
+ }
+
+ private void expandMultirefElement(String key, List parentKeys)
+ throws CyclicReferenceException {
+ if (parentKeys.contains(key))
+ throw new CyclicReferenceException();
+ parentKeys.add(key);
+ Node node = (Node) referenceMap.get(key);
+ expandNode(node, parentKeys);
+ resolvedReferences.add(key);
+ parentKeys.remove(key);
+ }
+
+ private void expandNode(Node node, List parentKeys)
+ throws CyclicReferenceException {
+ String href = getHrefForNode(node);
+ if (href != null) {
+ if (!resolvedReferences.contains(href)) {
+ expandMultirefElement(href, parentKeys);
+ }
+ copyMultirefContentsToParent(node, href);
+ }
+ if (node.hasChildNodes()) {
+ Node child = node.getFirstChild();
+ while (child != null) {
+ expandNode(child, parentKeys);
+ child = child.getNextSibling();
+ }
+ }
+ }
+
+ private void copyMultirefContentsToParent(Node parent, String multirefKey) {
+ Element multiRef = (Element) referenceMap.get(multirefKey);
+ Node child = multiRef.getFirstChild();
+ while (child != null) {
+ parent.appendChild(parent.getOwnerDocument()
+ .importNode(child, true));
+ child = child.getNextSibling();
+ }
+ parent.getAttributes().removeNamedItem("href");
+ }
+
+ private String getHrefForNode(Node node) {
+ String result = null;
+ NamedNodeMap nodemap = node.getAttributes();
+ if (nodemap != null) {
+ Node attrNode = nodemap.getNamedItem("href");
+ if (attrNode != null) {
+ result = attrNode.getNodeValue();
+ }
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedParser.java
new file mode 100644
index 0000000..ab45289
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseEncodedParser.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponseEncodedParser.java,v $
+ * Revision $Revision: 1.2 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2008/08/08 10:28:09 $
+ * by $Author: stain $
+ * Created on 08-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+/**
+ * SOAPResponseParser responsible for parsing SOAP responses from RPC/encoded
+ * based service, but that are not fragmented to multiref documents.
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponseEncodedParser implements SOAPResponseParser {
+
+ protected List<TypeDescriptor> outputDescriptors;
+
+ private boolean stripAttributes = false;
+
+ public SOAPResponseEncodedParser(List<TypeDescriptor> outputDescriptors) {
+ this.outputDescriptors = outputDescriptors;
+ }
+
+ /**
+ * Parses the response into a single XML document, which is placed in the
+ * outputMap together with the given output name. Namespaces and other
+ * attributes are stripped out according to stripAttributes.
+ *
+ * @param List
+ * @return Map
+ */
+ public Map parse(List response) throws Exception {
+
+ Map result = new HashMap();
+ Element mainBody = ((SOAPBodyElement) response.get(0)).getAsDOM();
+
+ for (TypeDescriptor descriptor : outputDescriptors) {
+ String outputName = descriptor.getName();
+
+ Node outputNode = getOutputNode(mainBody, outputName);
+ if (outputNode != null) {
+ String xml;
+
+ if (stripAttributes) {
+ stripAttributes(outputNode);
+ outputNode = removeNamespace(outputName,
+ (Element) outputNode);
+ }
+
+ xml = XMLUtils.ElementToString((Element) outputNode);
+ result.put(outputName, xml);
+ }
+ }
+
+ return result;
+ }
+
+ protected Node getOutputNode(Element mainBody, String outputName) {
+ // first try using body namespace ...
+ Node outputNode = mainBody.getElementsByTagNameNS(
+ mainBody.getNamespaceURI(), outputName).item(0);
+ // ... and if that doesn't work, try without namespace
+ if (outputNode == null) {
+ outputNode = mainBody.getElementsByTagName(outputName).item(
+ 0);
+ }
+ if (outputNode == null) { // if still null, and there is only 1
+ // output, take the first child
+ if (outputDescriptors.size() == 1
+ && mainBody.getChildNodes().getLength() == 1) {
+ outputNode = mainBody.getFirstChild();
+ }
+ }
+ return outputNode;
+ }
+
+ /**
+ * Removes the namespace from the surrounding element that represents the
+ * outputName. E.g. converts <ns1:element xmlns:ns1="http://someurl">...</ns1:element>
+ * to <element>...</element>
+ *
+ * @param outputName
+ * @param element
+ * @return
+ * @throws ParserConfigurationException
+ * @throws IOException
+ * @throws SAXException
+ */
+ protected Element removeNamespace(String outputName, Element element)
+ throws ParserConfigurationException, SAXException, IOException {
+ String xml;
+ String innerXML = XMLUtils.getInnerXMLString(element);
+ if (innerXML != null) {
+ xml = "<" + outputName + ">" + innerXML + "</" + outputName + ">";
+ } else {
+ xml = "<" + outputName + " />";
+ }
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+ Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
+ return doc.getDocumentElement();
+ }
+
+ protected void stripAttributes(Node node) {
+ List names = new ArrayList();
+ if (node.getAttributes() != null) {
+ for (int i = 0; i < node.getAttributes().getLength(); i++) {
+ names.add(node.getAttributes().item(i).getNodeName());
+ }
+ }
+
+ for (Iterator iterator = names.iterator(); iterator.hasNext();) {
+ node.getAttributes().removeNamedItem((String) iterator.next());
+ }
+
+ if (node.hasChildNodes()) {
+ Node child = node.getFirstChild();
+ while (child != null) {
+ stripAttributes(child);
+ child = child.getNextSibling();
+ }
+ }
+
+ }
+
+ /**
+ * determines whether attributes in the resulting XML should be stripped
+ * out, including namespace definitions, leading to XML that is much easier
+ * to read.
+ *
+ * @param stripAttributes
+ */
+ public void setStripAttributes(boolean stripAttributes) {
+ this.stripAttributes = stripAttributes;
+ }
+
+ public boolean getStripAttributes() {
+ return this.stripAttributes;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseLiteralParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseLiteralParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseLiteralParser.java
new file mode 100644
index 0000000..c27af9d
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseLiteralParser.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponseLiteralParser.java,v $
+ * Revision $Revision: 1.1 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2007/11/28 16:05:45 $
+ * by $Author: sowen70 $
+ * Created on 05-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Element;
+
+/**
+ * Responsible for parsing the SOAP response from calling a Literal based
+ * service.
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponseLiteralParser implements SOAPResponseParser {
+
+ List<TypeDescriptor>outputDescriptors;
+
+ public SOAPResponseLiteralParser(List<TypeDescriptor> outputDescriptors) {
+ this.outputDescriptors = outputDescriptors;
+ }
+
+ /**
+ * Expects a list containing a single SOAPBodyElement, the contents of which
+ * are transferred directly to the output, converted to a String, and placed
+ * into the outputMaP which is returned
+ *
+ * @return Map of the outputs
+ */
+ public Map parse(List response) throws Exception {
+ Map result = new HashMap();
+
+ if (response.size()>0) {
+ SOAPBodyElement rpcElement = (SOAPBodyElement) response.get(0);
+
+ Element dom = rpcElement.getAsDOM();
+
+ String outputName = getOutputName();
+ String xml = XMLUtils.ElementToString(dom);
+
+ result.put(outputName, xml);
+ }
+
+ return result;
+ }
+
+ protected String getOutputName() {
+ String result = "";
+ for (TypeDescriptor descriptor : outputDescriptors) {
+ String name=descriptor.getName();
+ if (!name.equals("attachmentList")) {
+ result = name;
+ break;
+ }
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParser.java
new file mode 100644
index 0000000..a2da0f8
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParser.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponseParser.java,v $
+ * Revision $Revision: 1.1 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2007/11/28 16:05:45 $
+ * by $Author: sowen70 $
+ * Created on 05-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Inteface that defines all parsers responsible for parsing SOAP responses from
+ * calling SOAP based webservices.
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public interface SOAPResponseParser {
+
+ /**
+ * All SOAPResponseParsers take a list of SOAPBodyElement's, resulting from
+ * invoking the service, and convert these into a suitable map of output
+ * DataThings.
+ *
+ * @param response -
+ * List of SOAPBodyElements
+ * @return Map of output DataThing's mapped to their output name
+ * @throws Exception
+ */
+ public Map parse(List response) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParserFactory.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParserFactory.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParserFactory.java
new file mode 100644
index 0000000..15df731
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponseParserFactory.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponseParserFactory.java,v $
+ * Revision $Revision: 1.1 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2007/11/28 16:05:45 $
+ * by $Author: sowen70 $
+ * Created on 05-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.util.List;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+/**
+ * A factory class that selects the correct type of SOAPResponseParser according
+ * to the service type , the types output of that service, and the response from
+ * invoking that service.
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponseParserFactory {
+
+ private static SOAPResponseParserFactory instance = new SOAPResponseParserFactory();
+
+ public static SOAPResponseParserFactory instance() {
+ return instance;
+ }
+
+ /**
+ * returns an instance of the appropriate type of SOAPResponseParser
+ *
+ * @param response -
+ * List of SOAPBodyElement's resulting from the service
+ * invokation.
+ * @param use -
+ * the type of the service - 'literal' or 'encoded'
+ * @param style -
+ * the style of the service - 'document' or 'rpc'
+ * @param outputDescriptors -
+ * the List of {@link TypeDescriptor}'s describing the service outputs
+ * @return
+ * @see SOAPResponseParser
+ */
+ public SOAPResponseParser create(List response, String use, String style,
+ List<TypeDescriptor> outputDescriptors) {
+
+ SOAPResponseParser result = null;
+
+ if (outputIsPrimitive(outputDescriptors)) {
+ if (use.equalsIgnoreCase("literal")) {
+ result = new SOAPResponsePrimitiveLiteralParser(outputDescriptors);
+ }
+ else {
+ result = new SOAPResponsePrimitiveParser(outputDescriptors);
+ }
+ } else if (use.equals("literal")) {
+ result = new SOAPResponseLiteralParser(outputDescriptors);
+ } else {
+ if (response.size() > 1) {
+ result = new SOAPResponseEncodedMultiRefParser(outputDescriptors);
+ } else {
+ result = new SOAPResponseEncodedParser(outputDescriptors);
+ }
+ }
+
+ return result;
+ }
+
+ private boolean outputIsPrimitive(List<TypeDescriptor> outputDescriptors) {
+ boolean result = true;
+ for (TypeDescriptor d : outputDescriptors) {
+ if (d.getMimeType().equals("'text/xml'")) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveLiteralParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveLiteralParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveLiteralParser.java
new file mode 100644
index 0000000..e26f146
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveLiteralParser.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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.soap;
+
+import java.io.ByteArrayInputStream;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * A response parser specifically for literal use services that return primative types.
+ * It extends the SOAPReponseLiteralParser, but unwraps the result from the enclosing XML
+ * to expose the primitive result.
+ *
+ * This is specially designed for unwrapped/literal type services, and RPC/literal services (untested).
+ * @author Stuart
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponsePrimitiveLiteralParser extends
+ SOAPResponseLiteralParser {
+
+ public SOAPResponsePrimitiveLiteralParser(List<TypeDescriptor> outputDescriptors) {
+ super(outputDescriptors);
+ }
+
+ @Override
+ public Map parse(List response) throws Exception {
+ Map result = super.parse(response);
+ Object dataValue = result.get(getOutputName());
+ if (dataValue!=null) {
+ String xml = dataValue.toString();
+
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+ Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
+
+ Node node = doc.getFirstChild();
+ result.put(getOutputName(), node.getFirstChild().getNodeValue());
+ }
+ return result;
+ }
+
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveParser.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveParser.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveParser.java
new file mode 100644
index 0000000..4bb0af4
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/SOAPResponsePrimitiveParser.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: SOAPResponsePrimitiveParser.java,v $
+ * Revision $Revision: 1.1 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2007/11/28 16:05:45 $
+ * by $Author: sowen70 $
+ * Created on 05-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.message.RPCElement;
+import org.apache.axis.message.RPCParam;
+
+/**
+ * SOAPResponseParser responsible for parsing soap responses that map to outputs
+ * that can be directly represented with Primitive types (i.e. int, String,
+ * String[]).
+ *
+ * @author sowen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class SOAPResponsePrimitiveParser implements SOAPResponseParser {
+
+ private List<String> outputNames;
+
+ public SOAPResponsePrimitiveParser(List<TypeDescriptor> outputDescriptors) {
+ outputNames=new ArrayList<String>();
+ for (TypeDescriptor desc : outputDescriptors) {
+ outputNames.add(desc.getName());
+ }
+ }
+
+ /**
+ * Parses each SOAPBodyElement for the primitive type, and places it in the
+ * output Map
+ */
+ public Map parse(List response) throws Exception {
+ Map result = new HashMap();
+ int c = 0;
+
+
+ RPCElement responseElement = (RPCElement) response.get(0);
+ List params = responseElement.getParams();
+
+ for (Iterator paramIterator = params.iterator(); paramIterator
+ .hasNext();) {
+ RPCParam param = (RPCParam) paramIterator.next();
+ Object value = param.getObjectValue();
+ // use the param name if it matches the outputname list,
+ // otherwise use the defined output name.
+ // Outputs should come back in the order of the outputNames
+ // as this is specified in the WSDL (only an issue for multiple
+ // outputs which is very rare, and is going to be documented as
+ // unrecommended for Taverna).
+ if (outputNames.contains(param.getName())) {
+ result.put(param.getName(), ObjectConverter.convertObject(value));
+ } else {
+ result.put(outputNames.get(c), value);
+ }
+ c++;
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/WSDLSOAPInvoker.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/WSDLSOAPInvoker.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/WSDLSOAPInvoker.java
new file mode 100644
index 0000000..36c50da
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/WSDLSOAPInvoker.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: WSDLSOAPInvoker.java,v $
+ * Revision $Revision: 1.7 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2008/08/28 19:39:28 $
+ * by $Author: stain $
+ * Created on 07-Apr-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.soap;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.activation.DataHandler;
+import javax.wsdl.WSDLException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.rpc.ServiceException;
+import javax.xml.soap.SOAPException;
+
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.parser.WSDLParser;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.EngineConfiguration;
+import org.apache.axis.attachments.AttachmentPart;
+import org.apache.axis.client.Call;
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.message.SOAPHeaderElement;
+import org.apache.axis.transport.http.HTTPTransport;
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+/**
+ * Invoke SOAP based webservices
+ *
+ * @author Stuart Owen
+ *
+ */
+@SuppressWarnings("unchecked")
+public class WSDLSOAPInvoker {
+
+ private static final String ATTACHMENT_LIST = "attachmentList";
+ private BodyBuilderFactory bodyBuilderFactory = BodyBuilderFactory.instance();
+ private WSDLParser parser;
+ private String operationName;
+ private List<String> outputNames;
+
+ private static Logger logger = Logger.getLogger(WSDLSOAPInvoker.class);
+
+ public WSDLSOAPInvoker(WSDLParser parser, String operationName,
+ List<String> outputNames) {
+ this.parser = parser;
+ this.operationName = operationName;
+ this.outputNames = outputNames;
+ }
+
+ protected String getOperationName() {
+ return operationName;
+ }
+
+ protected WSDLParser getParser() {
+ return parser;
+ }
+
+ protected List<String> getOutputNames() {
+ return outputNames;
+ }
+
+
+ /**
+ * Invokes the webservice with the supplied input Map, and returns a Map
+ * containing the outputs, mapped against their output names.
+ *
+ * @param inputMap
+ * @return
+ * @throws Exception
+ */
+ public Map<String, Object> invoke(Map inputMap) throws Exception {
+ return invoke(inputMap, (EngineConfiguration)null);
+ }
+
+ /**
+ * Invokes the webservice with the supplied input Map and axis engine configuration,
+ * and returns a Map containing the outputs, mapped against their output names.
+ */
+ public Map<String, Object> invoke(Map inputMap, EngineConfiguration config)
+ throws Exception {
+
+ Call call = getCall(config);
+ return invoke(inputMap, call);
+ }
+
+ /**
+ * Invokes the webservice with the supplied input Map and preconfigured axis call,
+ * and returns a Map containing the outputs, mapped against their output names.
+ */
+ public Map<String, Object> invoke(Map inputMap, Call call)
+ throws Exception {
+
+ call.setTimeout(getTimeout());
+
+ SOAPEnvelope requestEnv = makeRequestEnvelope(inputMap);
+// logger.info("Invoking service with SOAP envelope:\n"+requestEnv);
+
+ SOAPEnvelope responseEnv = invokeCall(call, requestEnv);
+
+// logger.info("Received SOAP response:\n"+responseEnv);
+
+ Map<String, Object> result;
+ if (responseEnv == null) {
+ if (outputNames.size() == 1
+ && outputNames.get(0).equals(ATTACHMENT_LIST)) {
+ // Could be axis 2 service with no output (TAV-617)
+ result = new HashMap<String, Object>();
+ } else {
+ throw new IllegalStateException(
+ "Missing expected outputs from service");
+ }
+ } else {
+ List response = responseEnv.getBodyElements();
+// logger.info("SOAP response was:" + response);
+ SOAPResponseParser parser = SOAPResponseParserFactory
+ .instance()
+ .create(
+ response,
+ getUse(),
+ getStyle(),
+ this.parser
+ .getOperationOutputParameters(operationName));
+ result = parser.parse(response);
+ }
+
+ result.put(ATTACHMENT_LIST, extractAttachments(call));
+
+ return result;
+ }
+
+ protected SOAPEnvelope makeRequestEnvelope(Map inputMap)
+ throws UnknownOperationException, IOException, WSDLException,
+ ParserConfigurationException, SOAPException, SAXException {
+
+ SOAPEnvelope requestEnv = new SOAPEnvelope();
+ for (SOAPHeaderElement headerElement : makeSoapHeaders()) {
+ requestEnv.addHeader(headerElement);
+ }
+ requestEnv.addBodyElement(makeSoapBody(inputMap));
+ return requestEnv;
+ }
+
+ protected List<SOAPHeaderElement> makeSoapHeaders() {
+ return Collections.emptyList();
+ }
+
+ protected SOAPBodyElement makeSoapBody(Map inputMap)
+ throws UnknownOperationException, IOException, WSDLException,
+ ParserConfigurationException, SOAPException, SAXException {
+ BodyBuilder builder = bodyBuilderFactory.create(parser,
+ operationName,
+ parser.getOperationInputParameters(operationName));
+ return builder.build(inputMap);
+ }
+
+ protected SOAPEnvelope invokeCall(Call call, SOAPEnvelope requestEnv) throws AxisFault {
+ return call.invoke(requestEnv);
+ }
+
+ /**
+ * Reads the property taverna.wsdl.timeout, default to 5 minutes if missing.
+ *
+ * @return
+ */
+ protected Integer getTimeout() {
+ int result = 300000;
+ String minutesStr = System.getProperty("taverna.wsdl.timeout");
+
+ if (minutesStr == null) {
+ // using default of 5 minutes
+ return result;
+ }
+ try {
+ int minutes = Integer.parseInt(minutesStr.trim());
+ result = minutes * 1000 * 60;
+ } catch (NumberFormatException e) {
+ logger.error("Non-integer timeout", e);
+ return result;
+ }
+ return result;
+ }
+
+ protected String getStyle() {
+ return parser.getStyle();
+ }
+
+ protected String getUse() throws UnknownOperationException {
+ return parser.getUse(operationName);
+ }
+
+ /**
+ * Returns an axis based Call, initialised for the operation that needs to
+ * be invoked
+ *
+ * @return
+ * @throws ServiceException
+ * @throws UnknownOperationException
+ * @throws MalformedURLException
+ * @throws WSDLException
+ * @throws WSIFException
+ */
+ protected Call getCall(EngineConfiguration config) throws ServiceException, UnknownOperationException, MalformedURLException {
+
+ org.apache.axis.client.Service service;
+ if (config==null) {
+ service = new org.apache.axis.client.Service();
+ }
+ else {
+ service = new org.apache.axis.client.Service(config);
+ }
+
+ Call call = new Call(service);
+
+ call.setTransport(new HTTPTransport());
+ call.setTargetEndpointAddress(parser.getOperationEndpointLocations(operationName).get(0));
+ //result.setPortName(parser.getPortType(operationName).getQName());
+ //result.setOperation(operationName);
+
+ String use = parser.getUse(operationName);
+ call.setUseSOAPAction(true);
+ call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR,
+ Boolean.FALSE);
+ call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS,
+ Boolean.FALSE);
+ call
+ .setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
+
+ if (parser.getSOAPActionURI(operationName)!=null) {
+ call.setSOAPActionURI(parser.getSOAPActionURI(operationName));
+ }
+
+ if (use.equalsIgnoreCase("literal")) {
+ call.setEncodingStyle(null);
+ }
+ return call;
+ }
+
+
+ /**
+ * Exctracts any attachments that result from invoking the service, and
+ * returns them as a List wrapped within a DataThing
+ *
+ * @param axisCall
+ * @return
+ * @throws SOAPException
+ * @throws IOException
+ */
+ protected List extractAttachments(Call axisCall)
+ throws SOAPException, IOException {
+ List attachmentList = new ArrayList();
+ if (axisCall.getResponseMessage() != null
+ && axisCall.getResponseMessage().getAttachments() != null) {
+ for (Iterator i = axisCall.getResponseMessage().getAttachments(); i
+ .hasNext();) {
+ AttachmentPart ap = (AttachmentPart) i.next();
+ DataHandler dh = ap.getDataHandler();
+ BufferedInputStream bis = new BufferedInputStream(dh
+ .getInputStream());
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int c;
+ while ((c = bis.read()) != -1) {
+ bos.write(c);
+ }
+ bis.close();
+ bos.close();
+ String mimeType = dh.getContentType();
+ if (mimeType.matches(".*image.*")
+ || mimeType.matches(".*octet.*")
+ || mimeType.matches(".*audio.*")
+ || mimeType.matches(".*application/zip.*")) {
+ attachmentList.add(bos.toByteArray());
+ } else {
+ attachmentList.add(new String(bos.toByteArray()));
+ }
+ }
+ }
+
+ return attachmentList;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/package.html
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/package.html b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/package.html
new file mode 100644
index 0000000..5fd36e5
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/soap/package.html
@@ -0,0 +1,5 @@
+<body>
+Contains classes required to invoke an endpoint for a SOAP based web-service described by a WSDL.<br>
+These classes are derived heavily from the original parsing classes from the Taverna 1 WSDLBasedProcessor and have been refactored<br>
+to remove references to to Taverna 1
+</body>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLInputSplitter.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLInputSplitter.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLInputSplitter.java
new file mode 100644
index 0000000..031de03
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLInputSplitter.java
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.BaseTypeDescriptor;
+import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.encoding.Base64;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.Namespace;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+
+public class XMLInputSplitter {
+
+ private TypeDescriptor typeDescriptor;
+ private String[] outputNames;
+ private String[] inputNames;
+ private String[] inputTypes;
+
+ public XMLInputSplitter(TypeDescriptor typeDescriptor, String inputNames[],
+ String inputTypes[], String[] outputNames) {
+ this.typeDescriptor = typeDescriptor;
+ this.outputNames = outputNames;
+ this.inputTypes = inputTypes;
+ this.inputNames = inputNames;
+ }
+
+ public Map<String, String> execute(Map<String, Object> inputMap)
+ throws JDOMException, IOException {
+ Map<String, String> result = new HashMap<String, String>();
+ Element outputElement = (this.typeDescriptor.getName().length() > 0 ? new Element(
+ this.typeDescriptor.getName())
+ : new Element(this.typeDescriptor.getType()));
+
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ executeForComplexType(inputMap, result, outputElement);
+
+ } else {
+ for (String key : inputMap.keySet()) {
+ Object dataObject = inputMap.get(key);
+
+ if (dataObject instanceof List) {
+ Element dataElement = buildElementFromObject(key, "");
+ for (Object dataItem : ((List<?>) dataObject)) {
+ Element itemElement = buildElementFromObject(key,
+ dataItem);
+ dataElement.addContent(itemElement);
+ }
+
+ XMLOutputter outputter = new XMLOutputter();
+ String xmlText = outputter.outputString(dataElement);
+
+ result.put(outputNames[0], xmlText);
+ } else {
+ Element dataElement = buildElementFromObject(key,
+ dataObject);
+ outputElement.addContent(dataElement);
+ XMLOutputter outputter = new XMLOutputter();
+ String xmlText = outputter.outputString(outputElement);
+ result.put(outputNames[0], xmlText);
+ }
+
+ }
+ }
+
+ return result;
+
+ }
+
+ private void executeForComplexType(Map<String, Object> inputMap,
+ Map<String, String> result, Element outputElement)
+ throws JDOMException, IOException {
+ ComplexTypeDescriptor complexDescriptor = (ComplexTypeDescriptor) typeDescriptor;
+ for (TypeDescriptor elementType : complexDescriptor.getElements()) {
+ String key = elementType.getName();
+ Object dataObject = inputMap.get(key);
+ if (dataObject==null) {
+ if (elementType.isOptional()) {
+ continue;
+ } if (elementType.isNillable()) {
+ dataObject = "xsi:nil";
+ } else {
+ dataObject="";
+ }
+ }
+
+ if (dataObject instanceof List) {
+ Element arrayElement = buildElementFromObject(key, "");
+
+ String itemkey = "item";
+ boolean wrapped = false;
+ if (elementType instanceof ArrayTypeDescriptor) {
+ wrapped = ((ArrayTypeDescriptor) elementType).isWrapped();
+ TypeDescriptor arrayElementType = ((ArrayTypeDescriptor) elementType)
+ .getElementType();
+ if (!wrapped) {
+ itemkey = elementType.getName();
+ } else {
+ if (arrayElementType.getName() != null
+ && arrayElementType.getName().length() > 0) {
+ itemkey = arrayElementType.getName();
+ } else {
+ itemkey = arrayElementType.getType();
+ }
+ }
+
+ }
+
+ for (Object itemObject : ((List<?>)dataObject)) {
+
+ Element dataElement = buildElementFromObject(itemkey,
+ itemObject);
+ dataElement.setNamespace(Namespace.getNamespace(elementType
+ .getNamespaceURI()));
+ if (!wrapped) {
+ dataElement.setName(itemkey);
+ outputElement.addContent(dataElement);
+ } else {
+ arrayElement.addContent(dataElement);
+ }
+ }
+ if (wrapped)
+ outputElement.addContent(arrayElement);
+ } else {
+ Element dataElement = buildElementFromObject(key, dataObject);
+ outputElement.addContent(dataElement);
+ }
+ }
+ for (TypeDescriptor attribute : complexDescriptor.getAttributes()) {
+ String key = attribute.getName();
+ Object dataObject = inputMap.get("1" + key);
+ if (dataObject == null) {
+ dataObject = inputMap.get(key);
+ }
+ if (dataObject != null) {
+ outputElement.setAttribute(key, dataObject.toString(), Namespace
+ .getNamespace(attribute.getNamespaceURI()));
+ }
+ }
+
+ outputElement.setNamespace(Namespace.getNamespace(typeDescriptor
+ .getNamespaceURI()));
+ XMLOutputter outputter = new XMLOutputter();
+ String xmlText = outputter.outputString(outputElement);
+ result.put(outputNames[0], xmlText);
+ }
+
+ private Element buildElementFromObject(String key, Object dataObject)
+ throws JDOMException, IOException {
+
+ Element dataElement = null;
+
+ if (isXMLInput(key)) {
+ dataElement = createDataElementForXMLInput(dataObject, key);
+ } else {
+ dataElement = new Element(key);
+ setDataElementNamespace(key, dataElement);
+ Namespace xsiNs = org.jdom.Namespace
+ .getNamespace("xsi",
+ "http://www.w3.org/2001/XMLSchema-instance");
+ if (dataObject.toString().equals("xsi:nil")) {
+ dataElement.setAttribute("nil", "true", xsiNs); // changes nil value
+ } else {
+ if (dataObject instanceof byte[]) {
+
+ dataElement
+ .setAttribute(
+ "type",
+ "xsd:base64Binary",
+ xsiNs);
+ dataObject = Base64
+ .encode(((byte[]) dataObject));
+ }
+ dataElement.setText(dataObject.toString());
+ }
+
+ }
+ return dataElement;
+ }
+
+ private Element createDataElementForXMLInput(Object dataObject, String key)
+ throws JDOMException, IOException {
+ Element dataElement = null;
+ String xml = dataObject.toString();
+ if (xml.length() > 0) {
+ Document doc = new SAXBuilder().build(new StringReader(xml));
+ dataElement = doc.getRootElement();
+ dataElement.detach();
+ } else {
+ dataElement = new Element(key);
+ }
+
+ setDataElementNamespace(key, dataElement);
+ return dataElement;
+ }
+
+ // set the namespace if it can be determined from the element TypeDescriptor
+ // by the key
+ private void setDataElementNamespace(String key, Element dataElement) {
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ TypeDescriptor elementTypeDescriptor = ((ComplexTypeDescriptor) typeDescriptor)
+ .elementForName(key);
+ if (elementTypeDescriptor != null) {
+ String nsURI = null;
+ if (elementTypeDescriptor instanceof BaseTypeDescriptor) {
+ nsURI = elementTypeDescriptor.getNamespaceURI();
+ // this is some protective code against old workflows that
+ // had the base element namespace incorrectly
+ // declared (it was using the type NS, rather than the
+ // element NS.
+ if (nsURI.contains("XMLSchema")
+ && nsURI.contains("http://www.w3.org")) {
+ nsURI = typeDescriptor.getNamespaceURI();
+ }
+ } else {
+ nsURI = elementTypeDescriptor.getNamespaceURI();
+ }
+ if (nsURI != null && nsURI.length() > 0) {
+ updateElementNamespace(dataElement, nsURI);
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the element namespace, and also iterates all descendant elements.
+ * If these elements have no default namespace, or is blank then it is also
+ * set to namespaceURI (JDOM by default will not set the child elements to
+ * the same namespace as the element modified but will override them with
+ * blank namespaces).
+ *
+ * @param dataElement
+ * @param namespaceURI
+ */
+ private void updateElementNamespace(Element dataElement, String namespaceURI) {
+ dataElement.setNamespace(Namespace.getNamespace(namespaceURI));
+ Iterator<?> iterator = dataElement.getDescendants();
+ while (iterator.hasNext()) {
+ Object descendantObject = iterator.next();
+ if (descendantObject instanceof Element) {
+ Element childElement = (Element) descendantObject;
+ if (childElement.getNamespaceURI() == null) {
+ childElement.setNamespace(Namespace
+ .getNamespace(namespaceURI));
+ }
+ }
+ }
+ }
+
+ private boolean isXMLInput(String key) {
+ boolean result = false;
+ for (int i = 0; i < inputNames.length; i++) {
+ if (inputNames[i].equals(key)) {
+ result = inputTypes[i].indexOf("'text/xml'") != -1;
+ }
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLOutputSplitter.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLOutputSplitter.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLOutputSplitter.java
new file mode 100644
index 0000000..4ad5061
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLOutputSplitter.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate. Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * 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
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename $RCSfile: XMLOutputSplitter.java,v $
+ * Revision $Revision: 1.2 $
+ * Release status $State: Exp $
+ * Last modified on $Date: 2008/08/08 10:28:07 $
+ * by $Author: stain $
+ * Created on 16-May-2006
+ *****************************************************************/
+package net.sf.taverna.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.BaseTypeDescriptor;
+import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import org.apache.axis.encoding.Base64;
+import org.jdom.Attribute;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+
+public class XMLOutputSplitter {
+
+ private TypeDescriptor typeDescriptor;
+ private String[] outputNames;
+ private String[] inputNames;
+ private String[] outputTypes;
+
+ public XMLOutputSplitter(TypeDescriptor typeDescriptor,
+ String[] outputNames, String[] outputTypes,String[] inputNames) {
+ this.typeDescriptor = typeDescriptor;
+ this.outputNames = outputNames;
+ this.inputNames = inputNames;
+ this.outputTypes = outputTypes;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, Object> execute(Map<String, String> inputMap)
+ throws XMLSplitterExecutionException {
+
+ Map<String, Object> result = new HashMap<String, Object>();
+ List<String> outputNameList = Arrays.asList(outputNames);
+
+ String xml = inputMap.get(inputNames[0]);
+ try {
+ Document doc = new SAXBuilder().build(new StringReader(xml));
+ List<Element> children = doc.getRootElement().getChildren();
+ if (typeDescriptor instanceof ArrayTypeDescriptor) {
+ if (outputNames.length > 1)
+ throw new XMLSplitterExecutionException(
+ "Unexpected, multiple output names for ArrayType");
+ executeForArrayType(result, children);
+ } else {
+ executeForComplexType(result, outputNameList, children, doc.getRootElement().getAttributes());
+ }
+
+ // populate missing outputs with empty strings for basic types,
+ // empty elements for complex/array types.
+ for (int i = 0; i < outputNames.length; i++) {
+ if (result.get(outputNames[i]) == null) {
+ if (outputTypes[i].equals("'text/xml'")) {
+ result
+ .put(outputNames[i], "<" + outputNames[i]
+ + " />");
+ } else if (outputTypes[i].startsWith("l('")) {
+ result.put(outputNames[i], new ArrayList<Object>());
+ } else {
+ result.put(outputNames[i], "");
+ }
+
+ }
+ }
+ } catch (JDOMException e) {
+ throw new XMLSplitterExecutionException("Unable to parse XML: " + xml, e);
+ } catch (IOException e) {
+ throw new XMLSplitterExecutionException("IOException parsing XML: " + xml,
+ e);
+ }
+
+ return result;
+ }
+
+ private void executeForArrayType(Map<String, Object> result,
+ List<Element> children) {
+ ArrayTypeDescriptor arrayDescriptor = (ArrayTypeDescriptor) typeDescriptor;
+ List<String> values = new ArrayList<String>();
+ XMLOutputter outputter = new XMLOutputter();
+
+ boolean isInnerBaseType = arrayDescriptor.getElementType() instanceof BaseTypeDescriptor;
+ if (isInnerBaseType) {
+ values = extractBaseTypeArrayFromChildren(children);
+ } else {
+ for (Element child : children) {
+ values.add(outputter.outputString(child));
+ }
+ }
+ result.put(outputNames[0], values);
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private void executeForComplexType(Map<String, Object> result,
+ List<String> outputNameList, List<Element> children, List<Attribute> list)
+ throws IOException {
+
+ XMLOutputter outputter = new XMLOutputter();
+ for (Element child : children) {
+
+ if (outputNameList.contains(child.getName())) {
+ int i = outputNameList.indexOf(child.getName());
+ TypeDescriptor descriptorForChild = ((ComplexTypeDescriptor) typeDescriptor)
+ .elementForName(outputNames[i]);
+ if (outputTypes[i].startsWith("l(")
+ && descriptorForChild instanceof ArrayTypeDescriptor
+ && !((ArrayTypeDescriptor) descriptorForChild)
+ .isWrapped()) {
+ boolean isXMLContent = outputTypes[i].contains("text/xml");
+ result.put(child.getName(), extractDataListFromChildList(
+ children, isXMLContent));
+ break;
+ } else {
+ if (outputTypes[i].equals("'text/xml'")
+ || outputTypes[i].equals("l('text/xml')")) {
+ String xmlText = outputter.outputString(child);
+ result.put(child.getName(), xmlText);
+ } else if (outputTypes[i]
+ .equals("'application/octet-stream'")) { // base64Binary
+
+ byte[] data = Base64.decode(child
+ .getText());
+ result.put(child.getName(), data);
+ } else if (outputTypes[i].equals("l('text/plain')")) { // an
+ // inner
+ // element
+ // containing
+ // a
+ // list
+ result.put(child.getName(),
+ extractBaseTypeArrayFromChildren(child
+ .getChildren()));
+ } else {
+ result.put(child.getName(), child.getText());
+ }
+ }
+ }
+ }
+ for (Attribute attribute : list) {
+ if (outputNameList.contains("1" + attribute.getName())) {
+ result.put("1" + attribute.getName(), attribute.getValue());
+ } else if (outputNameList.contains(attribute.getName())) {
+ result.put(attribute.getName(), attribute.getValue());
+ }
+ }
+ }
+
+ private List<String> extractDataListFromChildList(List<Element> children,
+ boolean isXMLContent) {
+ List<String> result = new ArrayList<String>();
+ XMLOutputter outputter = new XMLOutputter();
+ for (Element child : children) {
+ if (!isXMLContent) {
+ result.add(child.getTextTrim());
+ } else {
+ result.add(outputter.outputString(child));
+ }
+ }
+ return result;
+ }
+
+ private List<String> extractBaseTypeArrayFromChildren(List<Element> children) {
+ List<String> result = new ArrayList<String>();
+ for (Element child : children) {
+ result.add(child.getTextTrim());
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLSplitterExecutionException.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLSplitterExecutionException.java b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLSplitterExecutionException.java
new file mode 100644
index 0000000..6ec1720
--- /dev/null
+++ b/taverna-wsdl-generic/src/main/java/net/sf/taverna/wsdl/xmlsplitter/XMLSplitterExecutionException.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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.xmlsplitter;
+
+public class XMLSplitterExecutionException extends Exception {
+
+ private static final long serialVersionUID = 5623707293500493612L;
+
+ public XMLSplitterExecutionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ public XMLSplitterExecutionException(String msg) {
+ super(msg);
+ }
+}