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:58 UTC
[17/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-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLActivityHealthChecker.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLActivityHealthChecker.java
new file mode 100644
index 0000000..0437ff6
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLActivityHealthChecker.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.wsdl.WSDLException;
+import javax.xml.parsers.ParserConfigurationException;
+
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.RemoteHealthChecker;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+import net.sf.taverna.t2.workflowmodel.processor.activity.DisabledActivity;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.parser.WSDLParser;
+
+import org.xml.sax.SAXException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class WSDLActivityHealthChecker extends RemoteHealthChecker {
+
+ private Activity<?> activity;
+
+ public boolean canVisit(Object subject) {
+ if (subject == null) {
+ return false;
+ }
+ if (subject instanceof WSDLActivity) {
+ return true;
+ }
+ if (subject instanceof DisabledActivity) {
+ return (((DisabledActivity) subject).getActivity() instanceof WSDLActivity);
+ }
+ return false;
+ }
+
+ public VisitReport visit(Object o, List<Object> ancestors) {
+ List<VisitReport> reports = new ArrayList<VisitReport>();
+ activity = (Activity<?>) o;
+ String endpoint = null;
+
+ WSDLParser parser;
+ try {
+ JsonNode configuration = null;
+ if (activity instanceof WSDLActivity) {
+ configuration = ((WSDLActivity)activity).getConfiguration();
+ } else if (activity instanceof DisabledActivity) {
+ configuration = (JsonNode) ((DisabledActivity) activity).getActivityConfiguration();
+ }
+ endpoint = configuration.get("operation").get("wsdl").asText();
+ VisitReport wsdlEndpointReport = RemoteHealthChecker.contactEndpoint(activity, endpoint);
+ reports.add(wsdlEndpointReport);
+ if (!wsdlEndpointReport.getStatus().equals(Status.SEVERE)) {
+ parser = new WSDLParser(endpoint);
+
+ String operationName = configuration.get("operation").get("name").asText();
+ try {
+ reports.add(testStyleAndUse(endpoint,
+ parser,
+ operationName));
+ reports.add(testEndpoint(parser, operationName));
+ } catch (UnknownOperationException e) {
+ VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity,
+ "Operation not found", HealthCheck.UNKNOWN_OPERATION,
+ Status.SEVERE);
+ vr.setProperty("operationName", operationName);
+ vr.setProperty("endpoint", endpoint);
+ reports.add(vr);
+ }
+ }
+
+ } catch (ParserConfigurationException e) {
+ VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity, "Invalid WSDL", HealthCheck.BAD_WSDL, Status.SEVERE);
+ vr.setProperty("exception", e);
+ vr.setProperty("endpoint", endpoint);
+ reports.add(vr);
+ } catch (WSDLException e) {
+ VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity, "Invalid WSDL", HealthCheck.BAD_WSDL, Status.SEVERE);
+ vr.setProperty("exception", e);
+ vr.setProperty("endpoint", endpoint);
+ reports.add(vr);
+ } catch (IOException e) {
+ VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity, "Read problem", HealthCheck.IO_PROBLEM, Status.SEVERE);
+ vr.setProperty("exception", e);
+ vr.setProperty("endpoint", endpoint);
+ reports.add(vr);
+ } catch (SAXException e) {
+ VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity, "Invalid WSDL", HealthCheck.BAD_WSDL, Status.SEVERE);
+ vr.setProperty("exception", e);
+ vr.setProperty("endpoint", endpoint);
+ reports.add(vr);
+ }
+
+ Status status = VisitReport.getWorstStatus(reports);
+ VisitReport report = new VisitReport(HealthCheck.getInstance(), activity, "WSDL Activity report", HealthCheck.NO_PROBLEM,
+ status, reports);
+
+ return report;
+ }
+
+ public static boolean checkStyleAndUse(String style, String use) {
+ return !(style.equalsIgnoreCase("rpc") && use.equalsIgnoreCase("literal"));
+ }
+
+ private VisitReport testStyleAndUse(String endpoint, WSDLParser parser, String operationName) throws
+ UnknownOperationException {
+ VisitReport report;
+ String style = parser.getStyle().toLowerCase();
+ String use = "?";
+ use = parser.getUse(operationName).toLowerCase();
+ if (!checkStyleAndUse(style, use)) {
+ report = new VisitReport(HealthCheck.getInstance(), activity,
+ "Unsupported style", HealthCheck.UNSUPPORTED_STYLE,
+ Status.SEVERE);
+ report.setProperty("use", use);
+ report.setProperty("style", style);
+ report.setProperty("endpoint", endpoint);
+ } else {
+ report = new VisitReport(HealthCheck.getInstance(), activity, style + "/"
+ + use + " is OK", HealthCheck.NO_PROBLEM, Status.OK);
+ }
+ return report;
+ }
+
+ private VisitReport testEndpoint(WSDLParser parser, String operationName) {
+ List<VisitReport> reports = new ArrayList<VisitReport>();
+ List<String> endpoints = parser
+ .getOperationEndpointLocations(operationName);
+ for (String endpoint : endpoints) {
+ reports.add(RemoteHealthChecker.contactEndpoint(activity, endpoint));
+ }
+
+ Status status = VisitReport.getWorstStatus(reports);
+ if (reports.size()==1) {
+ return reports.get(0);
+ }
+ else if (reports.size()==0) {
+ VisitReport report = new VisitReport(HealthCheck.getInstance(), activity, "Service could not be located.", HealthCheck.NO_ENDPOINTS, Status.SEVERE);
+ report.setProperty("operationName", operationName);
+ return report;
+ }
+ else {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Endpoint tests", HealthCheck.NO_PROBLEM, status, reports);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLOperationConfigurationBean.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLOperationConfigurationBean.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLOperationConfigurationBean.java
new file mode 100644
index 0000000..ac012ae
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/WSDLOperationConfigurationBean.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (C) 2011 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.t2.activities.wsdl;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+
+/**
+ * Configuration for a WSDL operation.
+ *
+ * @author David Withers
+ */
+@ConfigurationBean(uri = WSDLActivity.URI + "/operation")
+public class WSDLOperationConfigurationBean {
+
+ private URI wsdl;
+ private String operationName;
+
+ public URI getWsdl() {
+ return wsdl;
+ }
+
+ @ConfigurationProperty(name = "wsdl", label = "WSDL URL", description = "The location of the WSDL definition for the web service")
+ public void setWsdl(URI wsdl) {
+ this.wsdl = wsdl;
+ }
+
+ public String getOperationName() {
+ return operationName;
+ }
+
+ @ConfigurationProperty(name = "name", label = "Operation Name", description = "The name of the WSDL operation")
+ public void setOperationName(String operationName) {
+ this.operationName = operationName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/package.html
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/package.html b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/package.html
new file mode 100644
index 0000000..e38a14e
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/package.html
@@ -0,0 +1,3 @@
+<body>
+Contains the activity classes required to interact with a WSDL based web-service.
+</body>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SSLUtilities.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SSLUtilities.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SSLUtilities.java
new file mode 100644
index 0000000..69033bb
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SSLUtilities.java
@@ -0,0 +1,151 @@
+package net.sf.taverna.t2.activities.wsdl.security;
+
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * This class provide various static methods that relax X509 certificate and
+ * hostname verification while using the SSL over the HTTP protocol.
+ * <p>
+ * Call:
+ * SSLUtilities.trustAllHostnames() to turn off the default hostname verification on HTTPS connection;
+ * SSLUtilities.trustAllHttpsCertificates() to turn off the default certificate validation on HTTPS connection.
+ * SSLUtilities.stopTrustingAllHttpsCertificates() to stop trusting all hosts' certificates and go back to default Java settings.
+ *
+ * @author Francis Labrie
+ */
+public final class SSLUtilities {
+
+ /**
+ * Hostname verifier.
+ */
+ private static HostnameVerifier hostnameVerifier;
+ /**
+ * Thrust managers.
+ */
+ private static TrustManager[] trustManagers;
+
+ /**
+ * Set the default Hostname Verifier to an instance of a fake class that
+ * trust all hostnames.
+ */
+ public static void trustAllHostnames() {
+ // Create a trust manager that does not validate certificate chains
+ if(hostnameVerifier == null) {
+ hostnameVerifier = new FakeHostnameVerifier();
+ } // if
+ // Install the all-trusting host name verifier:
+ HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
+ } // _trustAllHttpsCertificates
+
+ /**
+ * Set the default X509 Trust Manager to an instance of a fake class that
+ * trust all certificates, even the self-signed ones.
+ */
+ public static void trustAllHttpsCertificates() {
+ SSLContext context;
+
+ // Create a trust manager that does not validate certificate chains
+ if(trustManagers == null) {
+ trustManagers = new TrustManager[] {new FakeX509TrustManager()};
+ } // if
+ // Install the all-trusting trust manager:
+ try {
+ context = SSLContext.getInstance("SSL");
+ context.init(null, trustManagers, new SecureRandom());
+ } catch(GeneralSecurityException gse) {
+ throw new IllegalStateException(gse.getMessage());
+ } // catch
+ HttpsURLConnection.setDefaultSSLSocketFactory(context.
+ getSocketFactory());
+ } // _trustAllHttpsCertificates
+
+ /**
+ * This class implements a fake hostname verificator, trusting any host
+ * name.
+ *
+ * @author Francis Labrie
+ */
+ public static class FakeHostnameVerifier implements HostnameVerifier {
+
+ /**
+ * Always return true, indicating that the host name is
+ * an acceptable match with the server's authentication scheme.
+ *
+ * @param hostname the host name.
+ * @param session the SSL session used on the connection to
+ * host.
+ * @return the true boolean value
+ * indicating the host name is trusted.
+ */
+ public boolean verify(String hostname,
+ javax.net.ssl.SSLSession session) {
+ return(true);
+ } // verify
+ } // FakeHostnameVerifier
+
+ /**
+ * This class allow any X509 certificates to be used to authenticate the
+ * remote side of a secure socket, including self-signed certificates.
+ *
+ * @author Francis Labrie
+ */
+ public static class FakeX509TrustManager implements X509TrustManager {
+
+ /**
+ * Empty array of certificate authority certificates.
+ */
+ private static final X509Certificate[] _AcceptedIssuers =
+ new X509Certificate[] {};
+
+ /**
+ * Always trust for client SSL chain peer certificate
+ * chain with any authType authentication types.
+ *
+ * @param chain the peer certificate chain.
+ * @param authType the authentication type based on the client
+ * certificate.
+ */
+ public void checkClientTrusted(X509Certificate[] chain,
+ String authType) {
+ } // checkClientTrusted
+
+ /**
+ * Always trust for server SSL chain peer certificate
+ * chain with any authType exchange algorithm types.
+ *
+ * @param chain the peer certificate chain.
+ * @param authType the key exchange algorithm used.
+ */
+ public void checkServerTrusted(X509Certificate[] chain,
+ String authType) {
+ } // checkServerTrusted
+
+ /**
+ * Return an empty array of certificate authority certificates which
+ * are trusted for authenticating peers.
+ *
+ * @return a empty array of issuer certificates.
+ */
+ public X509Certificate[] getAcceptedIssuers() {
+ return(_AcceptedIssuers);
+ } // getAcceptedIssuers
+ } // FakeX509TrustManager
+
+ /**
+ * Stop trusting all certificates and go back to the default settings.
+ *
+ * @author Alex Nenadic
+ */
+ public static void stopTrustingAllHttpsCertificates(){
+ HttpsURLConnection.setDefaultSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());
+ }
+} // SSLUtilities
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SecurityProfiles.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SecurityProfiles.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SecurityProfiles.java
new file mode 100644
index 0000000..aa8084b
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/SecurityProfiles.java
@@ -0,0 +1,130 @@
+package net.sf.taverna.t2.activities.wsdl.security;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
+
+/**
+ * Various security profiles for Web services.
+ *
+ * @author Alex Nenadic
+ *
+ */
+public class SecurityProfiles {
+
+ public static URI SECURITY = URI.create(WSDLActivity.URI).resolve("wsdl/security");
+
+ /**
+ * Security profile for Web services that require
+ * UsernameToken authentication with plaintext password.
+ * Such services should typically be invoked over HTTPS.
+ */
+ public static final URI WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD = SECURITY.resolve("#WSSecurityUsernameTokenPlainTextPassword");
+ /**
+ * XML string for configuring Axis engine with wss4j handlers to handle setting security
+ * headers on the SOAP message for profile WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD.
+ */
+ public static final String WSSECURITY_USERNAMETOKEN_PLAINTEXTPASSWORD_CONFIG = "<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\">" +
+ "<globalConfiguration>" +
+ "<requestFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllSender\">" +
+ "<parameter name=\"action\" value=\"UsernameToken\"/>" +
+ "<parameter name=\"passwordType\" value=\"PasswordText\"/>" +
+ "</handler>"+
+ "</requestFlow>" +
+ "</globalConfiguration>" +
+ "<transport name=\"http\" pivot=\"java:org.apache.axis.transport.http.HTTPSender\"/>"+
+ "</deployment>";
+
+ /**
+ * Security profile for Web services that require
+ * UsernameToken authentication with digest password.
+ * Such services would typically be invoked over HTTPS.
+ */
+ public static final URI WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD = SECURITY.resolve("#WSSecurityUsernameTokenDigestPassword");
+ /**
+ * XML string for configuring Axis engine with wss4j handlers to handle setting security
+ * headers on the SOAP message for profile WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD.
+ */
+ public static final String WSSECURITY_USERNAMETOKEN_DIGESTPASSWORD_CONFIG = "<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\">" +
+ "<globalConfiguration>" +
+ "<requestFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllSender\">" +
+ "<parameter name=\"action\" value=\"UsernameToken\"/>" +
+ "<parameter name=\"passwordType\" value=\"PasswordDigest\"/>" +
+ "</handler>"+
+ "</requestFlow>" +
+ "</globalConfiguration>" +
+ "<transport name=\"http\" pivot=\"java:org.apache.axis.transport.http.HTTPSender\"/>"+
+ "</deployment>";
+
+ /**
+ * Security profile for Web services that require a timestamp SOAP header
+ * to be sent in addition to UsernameToken authentication with plaintext password.
+ * Such services should typically be invoked over HTTPS.
+ */
+ public static final URI WSSECURITY_TIMESTAMP_USERNAMETOKEN_PLAINTEXTPASSWORD = SECURITY.resolve("#WSSecurityTimestampUsernameTokenPlainTextPassword");
+ /**
+ * XML string for configuring Axis engine with wss4j handlers to handle setting security
+ * headers on the SOAP message for profile WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD.
+ */
+ public static final String WSSECURITY_TIMESTAMP_USERNAMETOKEN_PLAINTETPASSWORD_CONFIG = "<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\">" +
+ "<globalConfiguration>" +
+ "<requestFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllSender\">" +
+ "<parameter name=\"action\" value=\"Timestamp UsernameToken\"/>" +
+ "<parameter name=\"passwordType\" value=\"PasswordText\"/>" +
+ "</handler>"+
+ "</requestFlow>" +
+ "<responseFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllReceiver\">" +
+ "<parameter name=\"action\" value=\"Timestamp\"/>" +
+ "</handler>"+
+ "</responseFlow>" +
+ "</globalConfiguration>" +
+ "<transport name=\"http\" pivot=\"java:org.apache.axis.transport.http.HTTPSender\"/>"+
+ "</deployment>";
+
+ /**
+ * Security profile for Web services that require a timestamp SOAP header
+ * to be sent in addition to UsernameToken authentication with digest password.
+ * Such services would typically be invoked over HTTPS.
+ */
+ public static final URI WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD = SECURITY.resolve("#WSSecurityTimestampUsernameTokenDigestPassword");
+ /**
+ * XML string for configuring Axis engine with wss4j handlers to handle setting security
+ * headers on the SOAP message for profile WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD.
+ */
+ public static final String WSSECURITY_TIMESTAMP_USERNAMETOKEN_DIGESTPASSWORD_CONFIG = "<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\">" +
+ "<globalConfiguration>" +
+ "<requestFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllSender\">" +
+ "<parameter name=\"action\" value=\"Timestamp UsernameToken\"/>" +
+ "<parameter name=\"passwordType\" value=\"PasswordDigest\"/>" +
+ "</handler>"+
+ "</requestFlow>" +
+ "<responseFlow>" +
+ "<handler type=\"java:org.apache.ws.axis.security.WSDoAllReceiver\">" +
+ "<parameter name=\"action\" value=\"Timestamp\"/>" +
+ "</handler>"+
+ "</responseFlow>" +
+ "</globalConfiguration>" +
+ "<transport name=\"http\" pivot=\"java:org.apache.axis.transport.http.HTTPSender\"/>"+
+ "</deployment>";
+
+ /**
+ * Security profile for Web services that require HTTP Basic Authentication.
+ * There is no WS-Security involved.
+ * Such services should typically be invoked over HTTPS.
+ */
+ public static final URI HTTP_BASIC_AUTHN = SECURITY.resolve("#HTTPBasicAuthNPlainTextPassword");
+
+ /**
+ * Security profile for Web services that require HTTP Digest Authentication.
+ * There is no WS-Security involved.
+ * Such services would typically be invoked over HTTPS.
+ */
+ public static final URI HTTP_DIGEST_AUTHN = SECURITY.resolve("#HTTPDigestAuthN");
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/TavernaAxisCustomSSLSocketFactory.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/TavernaAxisCustomSSLSocketFactory.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/TavernaAxisCustomSSLSocketFactory.java
new file mode 100644
index 0000000..19ecb14
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/TavernaAxisCustomSSLSocketFactory.java
@@ -0,0 +1,40 @@
+package net.sf.taverna.t2.activities.wsdl.security;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.Hashtable;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.axis.components.net.BooleanHolder;
+import org.apache.axis.components.net.JSSESocketFactory;
+
+public class TavernaAxisCustomSSLSocketFactory extends JSSESocketFactory {
+
+
+ public TavernaAxisCustomSSLSocketFactory(Hashtable attributes) {
+ super(attributes);
+ }
+
+ @Override
+ public Socket create(String host, int port, StringBuffer otherHeaders,
+ BooleanHolder useFullURL) throws Exception {
+ // Make sure we always pick up the default socket factory from SSLContext, which is based on
+ // Taverna's Keystore and Truststore and gets updated when they get updated (it may have
+ // been updated in the menatime so just refresh it here just in case).
+ initFactory();
+ return super.create(host, port, otherHeaders, useFullURL);
+ }
+
+ @Override
+ protected void initFactory() throws IOException {
+ try{
+ // Set it to the default one from the SSLContext which is set to use Taverna's Keystore and Truststore
+ sslFactory = SSLContext.getDefault().getSocketFactory();
+ }
+ catch (Exception e) {
+ throw new IOException("Could not get the Taverna's default SSLSocketFactory from SSLContext",e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/ThreadLocalSSLSocketFactory.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/ThreadLocalSSLSocketFactory.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/ThreadLocalSSLSocketFactory.java
new file mode 100644
index 0000000..5660cbe
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/security/ThreadLocalSSLSocketFactory.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.security;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.log4j.Logger;
+
+/**
+ * An implementation of SSLSocketFactory which delegates to one of two internal
+ * SSLSocketFactory implementations. The implementation delegated to is
+ * determined by a thread local property and is either the default SSL socket or
+ * a customized one with a trust manager that allows the use of unsigned server
+ * certificates.
+ * <p>
+ * To set this as the default call install() prior to making any HTTPS
+ * connections, then bracket code which needs to trust unsigned certificates in
+ * the startTrustingEverything() and stopTrustingEverything() methods.
+ *
+ * @author Tom Oinn
+ *
+ */
+public class ThreadLocalSSLSocketFactory extends SSLSocketFactory {
+
+ private static Logger logger = Logger
+ .getLogger(ThreadLocalSSLSocketFactory.class);
+
+ /**
+ * Calls to open HTTPS connections will trust unsigned certificates afer
+ * this call is made, this is scoped to the current thread only.
+ */
+ public static void startTrustingEverything() {
+ threadLocalFactory.set(createAlwaysTrustingFactory());
+ }
+
+ /**
+ * Stop trusting unsigned certificates, reverting to the default behaviour
+ * for the current thread.
+ */
+ public static void stopTrustingEverything() {
+ threadLocalFactory.set(null);
+ }
+
+ /**
+ * Set this as the default global socket factory for HTTPS connections
+ */
+ public static void install() {
+ HttpsURLConnection
+ .setDefaultSSLSocketFactory(new ThreadLocalSSLSocketFactory());
+ }
+
+ /**
+ * Determine whether the current thread will trust unsigned certificates
+ */
+ public static boolean isTrustingEverything() {
+ return (threadLocalFactory.get() != null);
+ }
+
+ /**
+ * Never construct manually
+ */
+ private ThreadLocalSSLSocketFactory() {
+ super();
+ }
+
+ private static ThreadLocal<SSLSocketFactory> threadLocalFactory = new ThreadLocal<SSLSocketFactory>();
+
+ private static SSLSocketFactory createAlwaysTrustingFactory() {
+ SSLContext sc = null;
+ try {
+ sc = SSLContext.getInstance("SSL");
+ } catch (NoSuchAlgorithmException e1) {
+
+ logger.error("No SSL algorithm", e1);
+ }
+ TrustManager overlyTrusting = new X509TrustManager() {
+
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {
+
+ }
+
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {
+
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ };
+ try {
+ sc.init(null, new TrustManager[] { overlyTrusting },
+ new SecureRandom());
+ } catch (KeyManagementException e) {
+ logger.error("Unable to initialize SSLContext", e);
+ }
+ return sc.getSocketFactory();
+
+ }
+
+ private SSLSocketFactory getFactory() {
+ if (threadLocalFactory.get() == null) {
+ return (SSLSocketFactory) SSLSocketFactory.getDefault();
+ } else {
+ return threadLocalFactory.get();
+ }
+ }
+
+ @Override
+ public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3)
+ throws IOException {
+ return getFactory().createSocket(arg0, arg1, arg2, arg3);
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return getFactory().getDefaultCipherSuites();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return getFactory().getSupportedCipherSuites();
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return getFactory().createSocket();
+ }
+
+ @Override
+ public Socket createSocket(String arg0, int arg1) throws IOException,
+ UnknownHostException {
+ return getFactory().createSocket(arg0, arg1);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
+ return getFactory().createSocket(arg0, arg1);
+ }
+
+ @Override
+ public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3)
+ throws IOException, UnknownHostException {
+ return getFactory().createSocket(arg0, arg1, arg2, arg3);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2,
+ int arg3) throws IOException {
+ return getFactory().createSocket(arg0, arg1, arg2, arg3);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/wss4j/T2WSDoAllSender.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/wss4j/T2WSDoAllSender.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/wss4j/T2WSDoAllSender.java
new file mode 100644
index 0000000..7e9f909
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/wss4j/T2WSDoAllSender.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.wss4j;
+
+import java.util.Vector;
+
+//import net.sf.taverna.t2.security.agents.SAException;
+//import net.sf.taverna.t2.security.agents.WSSecurityAgent;
+
+//import org.apache.commons.logging.Log;
+//import org.apache.commons.logging.LogFactory;
+//import org.apache.log4j.Logger;
+import org.apache.ws.axis.security.WSDoAllSender;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+public class T2WSDoAllSender extends WSDoAllSender{
+
+ /**
+ * This is a security handler for wss4j that invokes security agents
+ * whenever access to the user's credentials (passwords, private keys)
+ * or secret keys is required. The security agent performs the necessary
+ * security operations on the message to be sent and returns the message.
+ */
+ private static final long serialVersionUID = 1L;
+
+ //private static Log log = LogFactory.getLog(T2WSDoAllSender.class.getName());
+
+ // private boolean doDebug = log.isDebugEnabled();
+
+ // private static Logger logger = Logger.getLogger(T2WSDoAllSender.class);
+
+ /**
+ * Performs all defined security actions to set-up the SOAP request.
+ *
+ * This method overrides the doSenderAction() method of WSHandler class
+ * by setting the actions to be executed to use T2 security agents.
+ *
+ *
+ * @param doAction a set defining the actions to do
+ * @param doc the request as DOM document
+ * @param reqData a data storage to pass values around bewteen methods
+ * @param actions a vector holding the actions to do in the order defined
+ * in the deployment file or property
+ * @throws WSSecurityException
+ */
+ @Override
+ protected void doSenderAction(int doAction, Document doc,
+ RequestData reqData, Vector actions,
+ boolean isRequest)
+ throws WSSecurityException {
+
+
+ boolean mu = decodeMustUnderstand(reqData);
+
+ WSSConfig wssConfig = WSSConfig.getNewInstance();
+
+ wssConfig
+ .setEnableSignatureConfirmation(decodeEnableSignatureConfirmation(reqData));
+
+ wssConfig
+ .setPrecisionInMilliSeconds(decodeTimestampPrecision(reqData));
+ reqData.setWssConfig(wssConfig);
+
+ Object mc = reqData.getMsgContext();
+ String actor = getString(WSHandlerConstants.ACTOR, mc);
+ reqData.setActor(actor);
+
+ WSSecHeader secHeader = new WSSecHeader(actor, mu);
+ secHeader.insertSecurityHeader(doc);
+
+ reqData.setSecHeader(secHeader);
+ reqData.setSoapConstants(WSSecurityUtil.getSOAPConstants(doc
+ .getDocumentElement()));
+ /*
+ * Here we have action, username, password, and actor, mustUnderstand.
+ * Now get the action specific parameters.
+ */
+ if ((doAction & WSConstants.UT) == WSConstants.UT) {
+ decodeUTParameter(reqData);
+ }
+ /*
+ * Here we have action, username, password, and actor, mustUnderstand.
+ * Now get the action specific parameters.
+ */
+ if ((doAction & WSConstants.UT_SIGN) == WSConstants.UT_SIGN) {
+ decodeUTParameter(reqData);
+ decodeSignatureParameter(reqData);
+ }
+ /*
+ * Get and check the Signature specific parameters first because they
+ * may be used for encryption too.
+ */
+ if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
+ reqData.setSigCrypto(loadSignatureCrypto(reqData));
+ decodeSignatureParameter(reqData);
+ }
+ /*
+ * If we need to handle signed SAML token then we need may of the
+ * Signature parameters. The handle procedure loads the signature crypto
+ * file on demand, thus don't do it here.
+ */
+ if ((doAction & WSConstants.ST_SIGNED) == WSConstants.ST_SIGNED) {
+ decodeSignatureParameter(reqData);
+ }
+ /*
+ * Set and check the encryption specific parameters, if necessary take
+ * over signature parameters username and crypto instance.
+ */
+ if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
+ reqData.setEncCrypto(loadEncryptionCrypto(reqData));
+ decodeEncryptionParameter(reqData);
+ }
+ /*
+ * If after all the parsing no Signature parts defined, set here a
+ * default set. This is necessary because we add SignatureConfirmation
+ * and therefore the default (Body) must be set here. The default setting
+ * in WSSignEnvelope doesn't work because the vector is not empty anymore.
+ */
+ if (reqData.getSignatureParts().isEmpty()) {
+ WSEncryptionPart encP = new WSEncryptionPart(reqData.getSoapConstants()
+ .getBodyQName().getLocalPart(), reqData.getSoapConstants()
+ .getEnvelopeURI(), "Content");
+ reqData.getSignatureParts().add(encP);
+ }
+ /*
+ * If SignatureConfirmation is enabled and this is a reqsponse then
+ * insert SignatureCOnfrmation elements, note their wsu:id in the signature
+ * parts. They will be signed automatically during a (probably) defined
+ * SIGN action.
+ */
+ if (wssConfig.isEnableSignatureConfirmation() && !isRequest) {
+ String done;
+ if ((done = (String) getProperty(reqData.getMsgContext(),
+ WSHandlerConstants.SIG_CONF_DONE)) == null
+ || !DONE.equals(done)) {
+ Vector results = null;
+ if ((results = (Vector) getProperty(reqData.getMsgContext(),
+ WSHandlerConstants.RECV_RESULTS)) != null) {
+ wssConfig.getAction(WSConstants.SC).execute(this, WSConstants.SC, doc, reqData);
+ }
+ }
+ }
+ /*
+ * Here we have all necessary information to perform the requested
+ * action(s).
+ */
+
+ // Get the security agent
+ /* WSSecurityAgent sa = (WSSecurityAgent) ((MessageContext)reqData.getMsgContext()).getProperty("security_agent");
+
+ // Perform security actions
+ for (int i = 0; i < actions.size(); i++) {
+
+ int actionToDo = ((Integer) actions.get(i)).intValue();
+ if (doDebug) {
+ log.debug("Performing Action: " + actionToDo);
+ }
+
+ switch (actionToDo) {
+ case WSConstants.UT:{
+ try {
+ sa.wssUsernameToken(doc, reqData);
+ } catch (SAException e) {
+ logger.error("", e);
+ } break;
+ }
+ case WSConstants.ENCR:
+ case WSConstants.SIGN:{//sa.wssSign(doc, reqData); break;}
+ case WSConstants.ST_SIGNED:
+ case WSConstants.ST_UNSIGNED:
+ case WSConstants.TS:
+ case WSConstants.UT_SIGN:
+ wssConfig.getAction(actionToDo).execute(this, actionToDo, doc, reqData);
+ break;
+ case WSConstants.NO_SERIALIZE:
+ reqData.setNoSerialization(true);
+ break;
+ }
+ } */
+
+ /*
+ * If this is a request then store all signature values. Add ours to
+ * already gathered values because of chained handlers, e.g. for
+ * other actors.
+ */
+
+ if (wssConfig.isEnableSignatureConfirmation() && isRequest) {
+ if (reqData.getSignatureValues().size() > 0) {
+ Vector sigv = null;
+ if ((sigv = (Vector) getProperty(reqData.getMsgContext(),
+ WSHandlerConstants.SEND_SIGV)) == null) {
+ sigv = new Vector();
+ setProperty(reqData.getMsgContext(),
+ WSHandlerConstants.SEND_SIGV, sigv);
+ }
+ // sigv.add(reqData.getSignatureValues());
+ sigv.addAll(reqData.getSignatureValues());
+ }
+ }
+ }
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/AddXMLSplitterEdit.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/AddXMLSplitterEdit.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/AddXMLSplitterEdit.java
new file mode 100644
index 0000000..a30c6a2
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/AddXMLSplitterEdit.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.t2.activities.wsdl.xmlsplitter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
+import net.sf.taverna.t2.workflowmodel.CompoundEdit;
+import net.sf.taverna.t2.workflowmodel.Dataflow;
+import net.sf.taverna.t2.workflowmodel.Edit;
+import net.sf.taverna.t2.workflowmodel.EditException;
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.EventForwardingOutputPort;
+import net.sf.taverna.t2.workflowmodel.EventHandlingInputPort;
+import net.sf.taverna.t2.workflowmodel.InputPort;
+import net.sf.taverna.t2.workflowmodel.OutputPort;
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.ProcessorInputPort;
+import net.sf.taverna.t2.workflowmodel.ProcessorOutputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+import net.sf.taverna.t2.workflowmodel.utils.Tools;
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class AddXMLSplitterEdit implements Edit<Dataflow> {
+
+ private final Edits edits;
+ private final Activity<?> activity;
+ private final String portName;
+ private final boolean isInput;
+ private CompoundEdit compoundEdit1 = null;
+ private Edit<?> linkUpEdit;
+ private final Dataflow dataflow;
+ private boolean applied = false;
+
+ public AddXMLSplitterEdit(Dataflow dataflow, Activity<?> activity,
+ String portName, boolean isInput, Edits edits) {
+ this.dataflow = dataflow;
+ this.activity = activity;
+ this.portName = portName;
+ this.isInput = isInput;
+ this.edits = edits;
+ }
+
+ @Override
+ public Dataflow doEdit() throws EditException {
+ if (applied) throw new EditException("Edit has already been applied!");
+ List<Edit<?>> editList = new ArrayList<Edit<?>>();
+
+ Activity<JsonNode> splitter = null;
+ String sourcePortName = "";
+ Processor sourceProcessor = null;
+ Activity<?> sourceActivity = null;
+
+ String sinkPortName = "";
+ Processor sinkProcessor = null;
+ Activity<?> sinkActivity = null;
+
+
+ Processor activityProcessor = findProcessorForActivity(dataflow,
+ activity);
+ if (activityProcessor == null) {
+ throw new EditException(
+ "Cannot find the processor that the activity belongs to");
+ }
+
+
+ String displayName = portName;
+ if (portName.equals("parameters")) {
+ displayName = isInput ? "input" : "output";
+ }
+ String processorName = activityProcessor.getLocalName();
+ String candidateName;
+ if (displayName.startsWith(processorName)) {
+ // No need to make GetRequest_GetRequestResponse
+ candidateName = displayName;
+ } else {
+ // Combine with processor name
+ String displayProcessorName;
+ if (activity instanceof XMLOutputSplitterActivity || activity instanceof XMLInputSplitterActivity) {
+ // For splitters on splitters - avoid adding up blah_bluh_blih_more_stuff
+ String[] processorNameSplit = processorName.replace("_input", "").replace("_output", "").split("_");
+ displayProcessorName = processorNameSplit[processorNameSplit.length-1];
+ } else {
+ displayProcessorName = activityProcessor.getLocalName();
+ }
+ candidateName = displayProcessorName + "_" + displayName;
+ }
+ String name = Tools.uniqueProcessorName(candidateName, dataflow);
+ Processor splitterProcessor = edits.createProcessor(name);
+
+ try {
+ if (activity instanceof XMLInputSplitterActivity) {
+ if (!isInput) {
+ throw new EditException(
+ "Can only add an input splitter to another input splitter");
+ }
+ TypeDescriptor descriptor = ((XMLInputSplitterActivity) activity)
+ .getTypeDescriptorForInputPort(portName);
+ if (descriptor instanceof ArrayTypeDescriptor && !((ArrayTypeDescriptor)descriptor).isWrapped()) {
+ descriptor=((ArrayTypeDescriptor)descriptor).getElementType();
+ }
+
+ JsonNode bean = XMLSplitterConfigurationBeanBuilder
+ .buildBeanForInput(descriptor);
+ splitter = new XMLInputSplitterActivity();
+ editList.add(edits.getConfigureActivityEdit(splitter, bean));
+
+ } else if (activity instanceof XMLOutputSplitterActivity) {
+ if (isInput) {
+ throw new EditException(
+ "Can only add an output splitter to another output splitter");
+ }
+ TypeDescriptor descriptor = ((XMLOutputSplitterActivity) activity)
+ .getTypeDescriptorForOutputPort(portName);
+
+ if (descriptor instanceof ArrayTypeDescriptor && !((ArrayTypeDescriptor)descriptor).isWrapped()) {
+ descriptor=((ArrayTypeDescriptor)descriptor).getElementType();
+ }
+
+ JsonNode bean = XMLSplitterConfigurationBeanBuilder
+ .buildBeanForOutput(descriptor);
+ splitter = new XMLOutputSplitterActivity();
+ editList.add(edits.getConfigureActivityEdit(splitter, bean));
+
+ } else if (activity instanceof WSDLActivity) {
+ if (isInput) {
+ TypeDescriptor descriptor = ((WSDLActivity) activity)
+ .getTypeDescriptorForInputPort(portName);
+ JsonNode bean = XMLSplitterConfigurationBeanBuilder
+ .buildBeanForInput(descriptor);
+ splitter = new XMLInputSplitterActivity();
+ editList
+ .add(edits.getConfigureActivityEdit(splitter, bean));
+ } else {
+ TypeDescriptor descriptor = ((WSDLActivity) activity)
+ .getTypeDescriptorForOutputPort(portName);
+ JsonNode bean = XMLSplitterConfigurationBeanBuilder
+ .buildBeanForOutput(descriptor);
+ splitter = new XMLOutputSplitterActivity();
+ editList
+ .add(edits.getConfigureActivityEdit(splitter, bean));
+ }
+ } else {
+ throw new EditException(
+ "The activity type is not suitable for adding xml processing processors");
+ }
+ } catch (Exception e) {
+ throw new EditException(
+ "An error occured whilst tyring to add an XMLSplitter to the activity:"
+ + activity, e);
+ }
+
+ if (isInput) {
+ sourcePortName = "output";
+ sinkPortName = portName;
+ sinkProcessor = activityProcessor;
+ sinkActivity = activity;
+ sourceProcessor = splitterProcessor;
+ sourceActivity = splitter;
+ }
+ else {
+ sourcePortName = portName;
+ sinkPortName = "input";
+ sinkProcessor = splitterProcessor;
+ sinkActivity = splitter;
+ sourceProcessor = activityProcessor;
+ sourceActivity = activity;
+ }
+
+ editList.add(edits.getDefaultDispatchStackEdit(splitterProcessor));
+ editList.add(edits.getAddActivityEdit(splitterProcessor, splitter));
+// editList.add(edits
+// .getMapProcessorPortsForActivityEdit(splitterProcessor));
+ editList.add(edits.getAddProcessorEdit(dataflow, splitterProcessor));
+
+ compoundEdit1 = new CompoundEdit(editList);
+ compoundEdit1.doEdit();
+
+ List<Edit<?>> linkUpEditList = new ArrayList<Edit<?>>();
+
+ EventForwardingOutputPort source = getSourcePort(sourceProcessor, sourceActivity,
+ sourcePortName, linkUpEditList);
+ EventHandlingInputPort sink = getSinkPort(sinkProcessor, sinkActivity, sinkPortName, linkUpEditList);
+
+ if (source == null)
+ throw new EditException(
+ "Unable to find the source port when linking up "
+ + sourcePortName + " to " + sinkPortName);
+ if (sink == null)
+ throw new EditException(
+ "Unable to find the sink port when linking up "
+ + sourcePortName + " to " + sinkPortName);
+
+ linkUpEditList.add(net.sf.taverna.t2.workflowmodel.utils.Tools.getCreateAndConnectDatalinkEdit(dataflow, source, sink, edits));
+
+ linkUpEdit = new CompoundEdit(linkUpEditList);
+ linkUpEdit.doEdit();
+ applied = true;
+ return dataflow;
+ }
+
+ private EventHandlingInputPort getSinkPort(Processor processor, Activity<?> activity,
+ String portName, List<Edit<?>> editList) {
+ InputPort activityPort = net.sf.taverna.t2.workflowmodel.utils.Tools.getActivityInputPort(activity, portName);
+ //check if processor port exists
+ EventHandlingInputPort input = net.sf.taverna.t2.workflowmodel.utils.Tools.getProcessorInputPort(processor, activity, activityPort);
+ if (input == null) {
+ //port doesn't exist so create a processor port and map it
+ ProcessorInputPort processorInputPort =
+ edits.createProcessorInputPort(processor, activityPort.getName(), activityPort.getDepth());
+ editList.add(edits.getAddProcessorInputPortEdit(processor, processorInputPort));
+ editList.add(edits.getAddActivityInputPortMappingEdit(activity, activityPort.getName(), activityPort.getName()));
+ input = processorInputPort;
+ }
+ return input;
+ }
+
+ private EventForwardingOutputPort getSourcePort(Processor processor, Activity<?> activity,
+ String portName, List<Edit<?>> editList) {
+ OutputPort activityPort = net.sf.taverna.t2.workflowmodel.utils.Tools.getActivityOutputPort(activity, portName);
+ //check if processor port exists
+ EventForwardingOutputPort output = net.sf.taverna.t2.workflowmodel.utils.Tools.getProcessorOutputPort(processor, activity, activityPort);
+ if (output == null) {
+ //port doesn't exist so create a processor port and map it
+ ProcessorOutputPort processorOutputPort =
+ edits.createProcessorOutputPort(processor, activityPort.getName(), activityPort.getDepth(), activityPort.getGranularDepth());
+ editList.add(edits.getAddProcessorOutputPortEdit(processor, processorOutputPort));
+ editList.add(edits.getAddActivityOutputPortMappingEdit(activity, activityPort.getName(), activityPort.getName()));
+ output = processorOutputPort;
+ }
+ return output;
+ }
+
+ @Override
+ public void undo() {
+ if (!applied) {
+ throw new RuntimeException(
+ "Attempt to undo edit that was never applied");
+ }
+ if (linkUpEdit.isApplied())
+ linkUpEdit.undo();
+ if (compoundEdit1.isApplied())
+ compoundEdit1.undo();
+ applied = false;
+ }
+
+ @Override
+ public boolean isApplied() {
+ return applied;
+ }
+
+ private Processor findProcessorForActivity(Dataflow dataflow,
+ Activity<?> activity) {
+ for (Processor p : dataflow.getProcessors()) {
+ for (Activity<?> a : p.getActivityList()) {
+ if (a == activity)
+ return p;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Object getSubject() {
+ return dataflow;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivity.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivity.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivity.java
new file mode 100644
index 0000000..3feb6f8
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivity.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.t2.activities.wsdl.InputPortTypeDescriptorActivity;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.ReferenceServiceException;
+import net.sf.taverna.t2.reference.T2Reference;
+import net.sf.taverna.t2.workflowmodel.OutputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.xmlsplitter.XMLInputSplitter;
+import net.sf.taverna.wsdl.xmlsplitter.XMLSplitterSerialisationHelper;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * An activity that replicates the behaviour of the Taverna 1 XMLInputSplitters.
+ *
+ * @author Stuart Owen
+ *
+ */
+public class XMLInputSplitterActivity extends AbstractAsynchronousActivity<JsonNode> implements InputPortTypeDescriptorActivity {
+
+ public static final String URI = "http://ns.taverna.org.uk/2010/activity/xml-splitter/in";
+
+ JsonNode configBean;
+ TypeDescriptor typeDescriptor;
+
+ @Override
+ public void configure(JsonNode configBean) throws ActivityConfigurationException {
+ this.configBean = configBean;
+
+ try {
+ String wrappedType = configBean.get("wrappedType").textValue();
+ Element element = new SAXBuilder().build(new StringReader(wrappedType)).getRootElement();
+ typeDescriptor = XMLSplitterSerialisationHelper.extensionXMLToTypeDescriptor(element);
+ } catch (JDOMException | IOException e) {
+ throw new ActivityConfigurationException(e);
+ }
+ }
+
+ @Override
+ public void executeAsynch(final Map<String, T2Reference> data,
+ final AsynchronousActivityCallback callback) {
+ callback.requestRun(new Runnable() {
+
+ public void run() {
+ try {
+ ReferenceService referenceService = callback.getContext().getReferenceService();
+ XMLInputSplitter splitter = createSplitter();
+ Map<String,Object> inputMap = buildInputMap(data,referenceService);
+ Map<String,String> outputMap = splitter.execute(inputMap);
+ callback.receiveResult(createOutputData(outputMap,referenceService), new int[0]);
+ }
+ catch(Exception e) {
+ callback.fail("Error in XMLInputSplitterActivity",e);
+ }
+ }
+
+ private Map<String, T2Reference> createOutputData(
+ Map<String, String> outputMap,ReferenceService referenceService) throws ReferenceServiceException {
+ Map<String,T2Reference> result = new HashMap<String, T2Reference>();
+ for (String outputName : outputMap.keySet()) {
+ String xmlOut = outputMap.get(outputName);
+ result.put(outputName, referenceService.register(xmlOut, 0, true, callback.getContext()));
+ }
+ return result;
+ }
+
+ private XMLInputSplitter createSplitter() {
+ List<String> inputNames = new ArrayList<String>();
+ List<String> inputTypes = new ArrayList<String>();
+ List<String> outputNames = new ArrayList<String>();
+
+ //FIXME: need to use the definition beans for now to get the mimetype. Need to use the actual InputPort once the mimetype becomes available again.
+ if (configBean.has("inputPorts")) {
+ for (JsonNode inputPort : configBean.get("inputPorts")) {
+ inputNames.add(inputPort.get("name").textValue());
+ inputTypes.add(inputPort.get("mimeType").textValue());
+ }
+ }
+
+ for (OutputPort outputPorts : getOutputPorts()) {
+ outputNames.add(outputPorts.getName());
+ }
+
+ return new XMLInputSplitter(typeDescriptor,inputNames.toArray(new String[]{}),inputTypes.toArray(new String[]{}),outputNames.toArray(new String[]{}));
+ }
+
+ private Map<String,Object> buildInputMap(Map<String, T2Reference> data,ReferenceService referenceService) throws ReferenceServiceException {
+ Map<String,Object> result = new HashMap<String, Object>();
+ for (String inputName : data.keySet()) {
+ T2Reference id = data.get(inputName);
+ result.put(inputName, referenceService.renderIdentifier(id,String.class, callback.getContext()));
+
+ }
+ return result;
+ }
+ });
+
+ }
+
+ @Override
+ public JsonNode getConfiguration() {
+ return configBean;
+ }
+
+ /**
+ * Returns a TypeDescriptor for the given port name. If the port cannot be found, or is not based upon a complex type, then null is returned.
+ * @param portName
+ * @return
+ */
+ public TypeDescriptor getTypeDescriptorForInputPort(String portName) {
+ TypeDescriptor result = null;
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ for (TypeDescriptor desc : ((ComplexTypeDescriptor)typeDescriptor).getElements()) {
+ if (desc.getName().equals(portName)) {
+ result = desc;
+ break;
+ }
+ }
+ }
+ else if (typeDescriptor instanceof ArrayTypeDescriptor) {
+ TypeDescriptor desc = ((ArrayTypeDescriptor)typeDescriptor).getElementType();
+
+ if (typeDescriptor.getName().equals(portName)) {
+ result = desc;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ */
+ public Map<String, TypeDescriptor> getTypeDescriptorsForInputPorts()
+ throws UnknownOperationException, IOException {
+ Map<String, TypeDescriptor> descriptors = new HashMap<String, TypeDescriptor>();
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ for (TypeDescriptor desc : ((ComplexTypeDescriptor)typeDescriptor).getElements()) {
+ descriptors.put(desc.getName(), desc);
+ }
+ }
+ else if (typeDescriptor instanceof ArrayTypeDescriptor) {
+ TypeDescriptor desc = ((ArrayTypeDescriptor)typeDescriptor).getElementType();
+ descriptors.put(typeDescriptor.getName(), desc);
+ }
+ return descriptors;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivityFactory.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivityFactory.java
new file mode 100644
index 0000000..2730637
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterActivityFactory.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (C) 2010 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * An {@link ActivityFactory} for creating <code>XMLInputSplitterActivity</code>.
+ *
+ * @author David Withers
+ */
+public class XMLInputSplitterActivityFactory implements ActivityFactory {
+
+ private Edits edits;
+
+ @Override
+ public XMLInputSplitterActivity createActivity() {
+ return new XMLInputSplitterActivity();
+ }
+
+ @Override
+ public URI getActivityType() {
+ return URI.create(XMLInputSplitterActivity.URI);
+ }
+
+ @Override
+ public JsonNode getActivityConfigurationSchema() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ return objectMapper.readTree(getClass().getResource("/xml-splitter.schema.json"));
+ } catch (IOException e) {
+ return objectMapper.createObjectNode();
+ }
+ }
+
+ public void setEdits(Edits edits) {
+ this.edits = edits;
+ }
+
+ @Override
+ public Set<ActivityInputPort> getInputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ Set<ActivityInputPort> inputPorts = new HashSet<>();
+ if (configuration.has("inputPorts")) {
+ for (JsonNode inputPort : configuration.get("inputPorts")) {
+ inputPorts.add(edits.createActivityInputPort(inputPort.get("name").textValue(),
+ inputPort.get("depth").intValue(), false, null, String.class));
+ }
+ }
+ return inputPorts;
+ }
+
+ @Override
+ public Set<ActivityOutputPort> getOutputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ Set<ActivityOutputPort> outputPorts = new HashSet<>();
+ if (configuration.has("outputPorts")) {
+ for (JsonNode outputPort : configuration.get("outputPorts")) {
+ outputPorts.add(edits.createActivityOutputPort(outputPort.get("name").textValue(),
+ outputPort.get("depth").intValue(), outputPort.get("granularDepth").intValue()));
+ }
+ }
+ return outputPorts;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterHealthChecker.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterHealthChecker.java
new file mode 100644
index 0000000..57d47d4
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLInputSplitterHealthChecker.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.List;
+
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+import net.sf.taverna.wsdl.xmlsplitter.XMLSplitterSerialisationHelper;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+public class XMLInputSplitterHealthChecker implements HealthChecker<XMLInputSplitterActivity> {
+
+ public boolean canVisit(Object subject) {
+ return subject!=null && subject instanceof XMLInputSplitterActivity;
+ }
+
+ public VisitReport visit(XMLInputSplitterActivity activity, List<Object> ancestors) {
+ Element element;
+ try {
+ String wrappedType = activity.getConfiguration().get("wrappedType").textValue();
+ element = new SAXBuilder().build(new StringReader(wrappedType)).getRootElement();
+ } catch (JDOMException | IOException e) {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Error reading wrapped type", HealthCheck.INVALID_CONFIGURATION, Status.SEVERE);
+ }
+ TypeDescriptor typeDescriptor = XMLSplitterSerialisationHelper.extensionXMLToTypeDescriptor(element);
+ if (typeDescriptor==null) {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Unknown datatype for port", HealthCheck.NULL_DATATYPE, Status.SEVERE);
+ }
+ else {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Recognized datatype", HealthCheck.NO_PROBLEM, Status.OK);
+ }
+ }
+
+ public boolean isTimeConsuming() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivity.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivity.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivity.java
new file mode 100644
index 0000000..8a63681
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivity.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.t2.activities.wsdl.OutputPortTypeDescriptorActivity;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.ReferenceServiceException;
+import net.sf.taverna.t2.reference.T2Reference;
+import net.sf.taverna.t2.workflowmodel.InputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;
+import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
+import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.xmlsplitter.XMLOutputSplitter;
+import net.sf.taverna.wsdl.xmlsplitter.XMLSplitterSerialisationHelper;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * An activity that replicates the behaviour of the Taverna 1 XMLOutputSplitter.
+ *
+ * @author Stuart Owen
+ *
+ */
+public class XMLOutputSplitterActivity extends
+ AbstractAsynchronousActivity<JsonNode> implements
+ OutputPortTypeDescriptorActivity {
+
+ public static final String URI = "http://ns.taverna.org.uk/2010/activity/xml-splitter/out";
+
+ JsonNode configBean;
+ TypeDescriptor typeDescriptor;
+
+ @Override
+ public void configure(JsonNode configBean)
+ throws ActivityConfigurationException {
+ this.configBean = configBean;
+
+ try {
+ String wrappedType = configBean.get("wrappedType").textValue();
+ Element element = new SAXBuilder().build(new StringReader(wrappedType)).getRootElement();
+ typeDescriptor = XMLSplitterSerialisationHelper.extensionXMLToTypeDescriptor(element);
+ } catch (JDOMException | IOException e) {
+ throw new ActivityConfigurationException(e);
+ }
+ }
+
+ @Override
+ public void executeAsynch(final Map<String, T2Reference> data,
+ final AsynchronousActivityCallback callback) {
+ callback.requestRun(new Runnable() {
+
+ public void run() {
+ try {
+ ReferenceService referenceService = callback.getContext()
+ .getReferenceService();
+ XMLOutputSplitter splitter = createSplitter();
+ Map<String, String> inputMap = buildInputMap(data,
+ referenceService);
+ Map<String, Object> outputMap = splitter.execute(inputMap);
+ callback.receiveResult(createOutputData(outputMap,
+ referenceService), new int[0]);
+ } catch (Exception e) {
+ callback.fail("Error in XMLInputSplitterActivity", e);
+ }
+ }
+
+ private Map<String, T2Reference> createOutputData(
+ Map<String, Object> outputMap,
+ ReferenceService referenceService)
+ throws ReferenceServiceException {
+ Map<String, T2Reference> result = new HashMap<String, T2Reference>();
+ for (String outputName : outputMap.keySet()) {
+ Object output = outputMap.get(outputName);
+ // TODO check if the output can be anything other than
+ // String or List
+ if (output instanceof List) {
+ result.put(outputName, referenceService.register(
+ output, 1, true, callback.getContext()));
+ } else {
+ result.put(outputName, referenceService.register(
+ output, 0, true, callback.getContext()));
+ }
+ }
+ return result;
+ }
+
+ private XMLOutputSplitter createSplitter() {
+ List<String> inputNames = new ArrayList<String>();
+ List<String> outputTypes = new ArrayList<String>();
+ List<String> outputNames = new ArrayList<String>();
+
+ // FIXME: need to use the definition beans for now to get the
+ // mimetype. Need to use the actual InputPort once the mimetype
+ // becomes available again.
+ if (configBean.has("outputPorts")) {
+ for (JsonNode outputPort : configBean.get("outputPorts")) {
+ outputNames.add(outputPort.get("name").textValue());
+ outputTypes.add(outputPort.get("mimeType").textValue());
+ }
+ }
+
+ for (InputPort outputPorts : getInputPorts()) {
+ inputNames.add(outputPorts.getName());
+ }
+
+ return new XMLOutputSplitter(typeDescriptor, outputNames
+ .toArray(new String[] {}), outputTypes
+ .toArray(new String[] {}), inputNames
+ .toArray(new String[] {}));
+ }
+
+ private Map<String, String> buildInputMap(
+ Map<String, T2Reference> data,
+ ReferenceService referenceService)
+ throws ReferenceServiceException {
+ Map<String, String> result = new HashMap<String, String>();
+ for (String inputName : data.keySet()) {
+ T2Reference id = data.get(inputName);
+ result.put(inputName, (String) referenceService
+ .renderIdentifier(id, String.class, callback
+ .getContext()));
+
+ }
+ return result;
+ }
+ });
+ }
+
+ @Override
+ public JsonNode getConfiguration() {
+ return configBean;
+ }
+
+ public TypeDescriptor getTypeDescriptorForOutputPort(String portName) {
+ TypeDescriptor result = null;
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ for (TypeDescriptor desc : ((ComplexTypeDescriptor) typeDescriptor)
+ .getElements()) {
+ if (desc.getName().equals(portName)) {
+ result = desc;
+ break;
+ }
+ }
+ }
+ else if (typeDescriptor instanceof ArrayTypeDescriptor) {
+ TypeDescriptor desc = ((ArrayTypeDescriptor)typeDescriptor).getElementType();
+
+ if (typeDescriptor.getName().equals(portName)) {
+ result = desc;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ */
+ public Map<String, TypeDescriptor> getTypeDescriptorsForOutputPorts()
+ throws UnknownOperationException, IOException {
+ Map<String, TypeDescriptor> descriptors = new HashMap<String, TypeDescriptor>();
+ if (typeDescriptor instanceof ComplexTypeDescriptor) {
+ for (TypeDescriptor desc : ((ComplexTypeDescriptor) typeDescriptor)
+ .getElements()) {
+ descriptors.put(desc.getName(), desc);
+ }
+ }
+ else if (typeDescriptor instanceof ArrayTypeDescriptor) {
+ TypeDescriptor desc = ((ArrayTypeDescriptor)typeDescriptor).getElementType();
+ descriptors.put(typeDescriptor.getName(), desc);
+ }
+ return descriptors;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivityFactory.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivityFactory.java
new file mode 100644
index 0000000..a4272e1
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterActivityFactory.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (C) 2010 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+
+/**
+ * An {@link ActivityFactory} for creating <code>XMLOutputSplitterActivity</code>.
+ *
+ * @author David Withers
+ */
+public class XMLOutputSplitterActivityFactory implements ActivityFactory {
+
+ private Edits edits;
+
+ @Override
+ public XMLOutputSplitterActivity createActivity() {
+ return new XMLOutputSplitterActivity();
+ }
+
+ @Override
+ public URI getActivityType() {
+ return URI.create(XMLOutputSplitterActivity.URI);
+ }
+
+ @Override
+ public JsonNode getActivityConfigurationSchema() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ return objectMapper.readTree(getClass().getResource("/xml-splitter.schema.json"));
+ } catch (IOException e) {
+ return objectMapper.createObjectNode();
+ }
+ }
+
+ @Override
+ public Set<ActivityInputPort> getInputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ Set<ActivityInputPort> inputPorts = new HashSet<>();
+ if (configuration.has("inputPorts")) {
+ for (JsonNode inputPort : configuration.get("inputPorts")) {
+ inputPorts.add(edits.createActivityInputPort(inputPort.get("name").textValue(),
+ inputPort.get("depth").intValue(), false, null, String.class));
+ }
+ }
+ return inputPorts;
+ }
+
+ @Override
+ public Set<ActivityOutputPort> getOutputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ Set<ActivityOutputPort> outputPorts = new HashSet<>();
+ if (configuration.has("outputPorts")) {
+ for (JsonNode outputPort : configuration.get("outputPorts")) {
+ outputPorts.add(edits.createActivityOutputPort(outputPort.get("name").textValue(),
+ outputPort.get("depth").intValue(), outputPort.get("granularDepth").intValue()));
+ }
+ }
+ return outputPorts;
+ }
+
+ public void setEdits(Edits edits) {
+ this.edits = edits;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterHealthChecker.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterHealthChecker.java
new file mode 100644
index 0000000..7634b6d
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLOutputSplitterHealthChecker.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.xmlsplitter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.List;
+
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.wsdl.parser.TypeDescriptor;
+import net.sf.taverna.wsdl.xmlsplitter.XMLSplitterSerialisationHelper;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+public class XMLOutputSplitterHealthChecker implements HealthChecker<XMLOutputSplitterActivity> {
+
+ public boolean canVisit(Object subject) {
+ return subject!=null && subject instanceof XMLOutputSplitterActivity;
+ }
+
+ public VisitReport visit(XMLOutputSplitterActivity activity, List<Object> ancestors) {
+ Element element;
+ try {
+ String wrappedType = activity.getConfiguration().get("wrappedType").textValue();
+ element = new SAXBuilder().build(new StringReader(wrappedType)).getRootElement();
+ } catch (JDOMException | IOException e) {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Error reading wrapped type", HealthCheck.INVALID_CONFIGURATION, Status.SEVERE);
+ }
+ TypeDescriptor typeDescriptor = XMLSplitterSerialisationHelper.extensionXMLToTypeDescriptor(element);
+ if (typeDescriptor==null) {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Unknown datatype for port", HealthCheck.NULL_DATATYPE, Status.SEVERE);
+ }
+ else {
+ return new VisitReport(HealthCheck.getInstance(), activity, "Recognized datatype", HealthCheck.NO_PROBLEM, Status.OK);
+ }
+ }
+
+ public boolean isTimeConsuming() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLSplitterConfigurationBean.java
----------------------------------------------------------------------
diff --git a/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLSplitterConfigurationBean.java b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLSplitterConfigurationBean.java
new file mode 100644
index 0000000..2045260
--- /dev/null
+++ b/taverna-wsdl-activity/src/main/java/net/sf/taverna/t2/activities/wsdl/xmlsplitter/XMLSplitterConfigurationBean.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.t2.activities.wsdl.xmlsplitter;
+
+import org.jdom.Element;
+
+import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityPortsDefinitionBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+
+@ConfigurationBean(uri = "http://ns.taverna.org.uk/2010/activity/xml-splitter#Config")
+public class XMLSplitterConfigurationBean extends ActivityPortsDefinitionBean {
+ Element wrappedTypeXML;
+
+ public Element getWrappedTypeXML() {
+ return wrappedTypeXML;
+ }
+
+ @ConfigurationProperty(name = "wrappedType", label = "Wrapped Type XML")
+ public void setWrappedTypeXML(Element wrappedTypeXML) {
+ this.wrappedTypeXML = wrappedTypeXML;
+ }
+
+}