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/17 12:46:47 UTC
[20/50] [abbrv] incubator-taverna-plugin-bioinformatics git commit:
taverna-biomoby-activity/
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/BiomobyObjectActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/BiomobyObjectActivityHealthChecker.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/BiomobyObjectActivityHealthChecker.java
new file mode 100644
index 0000000..7db539a
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/BiomobyObjectActivityHealthChecker.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+
+import net.sf.taverna.t2.workflowmodel.health.RemoteHealthChecker;
+import net.sf.taverna.t2.workflowmodel.processor.activity.DisabledActivity;
+
+/**
+ * A health checker for the Biomoby Object activity.
+ *
+ * @author David Withers
+ */
+public class BiomobyObjectActivityHealthChecker extends RemoteHealthChecker {
+
+ public boolean canVisit(Object subject) {
+ if (subject == null) {
+ return false;
+ }
+ if (subject instanceof BiomobyObjectActivity) {
+ return true;
+ }
+ if (subject instanceof DisabledActivity) {
+ return (((DisabledActivity) subject).getActivity() instanceof BiomobyObjectActivity);
+ }
+ return false;
+ }
+
+ public VisitReport visit(Object o, List<Object> ancestors) {
+ Activity activity = (Activity) o;
+ BiomobyObjectActivityConfigurationBean configuration = null;
+ if (activity instanceof BiomobyObjectActivity) {
+ configuration = (BiomobyObjectActivityConfigurationBean) activity.getConfiguration();
+ } else if (activity instanceof DisabledActivity) {
+ configuration = (BiomobyObjectActivityConfigurationBean) ((DisabledActivity) activity).getActivityConfiguration();
+ }
+ return contactEndpoint(activity, configuration.getMobyEndpoint());
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncCgiService.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncCgiService.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncCgiService.java
new file mode 100644
index 0000000..552dd34
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncCgiService.java
@@ -0,0 +1,517 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.log4j.Logger;
+import org.biomoby.shared.MobyException;
+import org.biomoby.shared.MobyPrefixResolver;
+import org.biomoby.shared.parser.MobyTags;
+import org.biomoby.w3c.addressing.EndpointReference;
+import org.jdom.Element;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+import org.omg.lsae.notifications.AnalysisEvent;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * This class contains one method that is used to execute asynchronous HTTP POST
+ * services
+ *
+ * @author Edward Kawas
+ *
+ */
+public class ExecuteAsyncCgiService {
+
+ private static final String GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION = "http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest";
+ private static final String DESTROY_RESOURCE_ACTION = "http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyRequest";
+
+ private static final String RESOURCE_PROPERTIES_NS = "http://docs.oasis-open.org/wsrf/rp-2";
+ private static final String RESULT_PREFIX = "result_";
+ private static final String STATUS_PREFIX = "status_";
+ private static Logger logger = Logger
+ .getLogger(ExecuteAsyncCgiService.class);
+
+ /**
+ *
+ * @param url
+ * @param serviceName
+ * @param xml
+ * @return
+ */
+ public static String executeMobyCgiAsyncService(String url,
+ String serviceName, String xml) throws MobyException {
+
+ // First, let's get the queryIds
+ org.w3c.dom.Document message = null;
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ message = db.parse(new InputSource(new StringReader(xml)));
+ } catch (Throwable t) {
+ throw new MobyException("Error while parsing input query", t);
+ }
+
+ NodeList l_data = message.getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE, MobyTags.MOBYDATA);
+ if (l_data == null || l_data.getLength() == 0) {
+ l_data = message.getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE_INVALID,
+ MobyTags.MOBYDATA);
+ }
+
+ // Freeing resources
+ message = null;
+
+ if (l_data == null || l_data.getLength() == 0) {
+ throw new MobyException("Empty asynchronous MOBY query!");
+ }
+
+ int nnode = l_data.getLength();
+ String[] queryIds = new String[nnode];
+ String[] tmpQueryIds = new String[nnode];
+ String[] results = new String[nnode];
+ for (int inode = 0; inode < nnode; inode++) {
+ String queryId = null;
+
+ org.w3c.dom.Element mdata = (org.w3c.dom.Element) l_data
+ .item(inode);
+
+ queryId = mdata.getAttribute(MobyTags.QUERYID);
+ if (queryId == null || queryId.length() == 0)
+ queryId = mdata
+ .getAttributeNS(MobyPrefixResolver.MOBY_XML_NAMESPACE,
+ MobyTags.QUERYID);
+ if (queryId == null || queryId.length() == 0)
+ queryId = mdata.getAttributeNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE_INVALID,
+ MobyTags.QUERYID);
+
+ if (queryId == null || queryId.length() == 0) {
+ throw new MobyException(
+ "Unable to extract queryId for outgoing MOBY message");
+ }
+
+ tmpQueryIds[inode] = queryIds[inode] = queryId;
+ results[inode] = null;
+ }
+
+ // Freeing resources
+ l_data = null;
+
+ // Second, let's launch
+ EndpointReference epr = launchCgiAsyncService(url, xml);
+
+ // Third, waiting for the results
+ try {
+ // FIXME - add appropriate values here
+ long pollingInterval = 1000L;
+ double backoff = 1.0;
+
+ // Max: one minute pollings
+ long maxPollingInterval = 60000L;
+
+ // Min: one second
+ if (pollingInterval <= 0L)
+ pollingInterval = 1000L;
+
+ // Backoff: must be bigger than 1.0
+ if (backoff <= 1.0)
+ backoff = 1.5;
+
+ do {
+ try {
+ Thread.sleep(pollingInterval);
+ } catch (InterruptedException ie) {
+ // DoNothing(R)
+ }
+
+ if (pollingInterval != maxPollingInterval) {
+ pollingInterval = (long) ((double) pollingInterval * backoff);
+ if (pollingInterval > maxPollingInterval) {
+ pollingInterval = maxPollingInterval;
+ }
+ }
+ } while (pollAsyncCgiService(serviceName, url, epr, tmpQueryIds,
+ results));
+ } finally {
+
+ // Call destroy on this service ....
+ freeCgiAsyncResources(url, epr);
+
+ }
+
+ // Fourth, assembling back the results
+
+ // Results array already contains mobyData
+ Element[] mobydatas = new Element[results.length];
+ for (int x = 0; x < results.length; x++) {
+ // TODO remove the extra wrapping from our result
+ try {
+ Element inputElement = XMLUtilities.getDOMDocument(results[x])
+ .getRootElement();
+ if (inputElement.getName().indexOf(
+ "GetMultipleResourcePropertiesResponse") >= 0)
+ if (inputElement.getChildren().size() > 0)
+ inputElement = (Element) inputElement.getChildren()
+ .get(0);
+ if (inputElement.getName().indexOf("result_") >= 0)
+ if (inputElement.getChildren().size() > 0)
+ inputElement = (Element) inputElement.getChildren()
+ .get(0);
+ // replace results[x]
+ mobydatas[x] = inputElement;
+ } catch (MobyException e) {
+ // TODO what should i do?
+ }
+ }
+ Element e = null;
+ try {
+ e = XMLUtilities.createMultipleInvokations(mobydatas);
+ } catch (Exception ex) {
+ logger
+ .error("There was a problem creating our XML message ...",
+ ex);
+ }
+ // Fifth, returning results
+ return e == null ? "" : new XMLOutputter(Format.getPrettyFormat())
+ .outputString(e);
+ }
+
+ private static void freeCgiAsyncResources(String endpoint,
+ EndpointReference epr) throws MobyException {
+ // construct the Httpclient
+ HttpClient client = new HttpClient();
+ client.getParams().setParameter("http.useragent", "jMoby/Taverna2");
+ // create the post method
+ PostMethod method = new PostMethod(endpoint + "/destroy");
+
+ // put our data in the request
+ RequestEntity entity;
+ try {
+ entity = new StringRequestEntity(
+ "<Destroy xmlns=\"http://docs.oasis-open.org/wsrf/rl-2\"/>",
+ "text/xml", null);
+ } catch (UnsupportedEncodingException e) {
+ throw new MobyException("Problem posting data to webservice", e);
+ }
+ method.setRequestEntity(entity);
+
+ // set the header
+ StringBuffer httpheader = new StringBuffer();
+ httpheader.append("<moby-wsrf>");
+ httpheader
+ .append("<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">"
+ + DESTROY_RESOURCE_ACTION + "</wsa:Action>");
+ httpheader
+ .append("<wsa:To xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsu:Id=\"To\">"
+ + endpoint + "</wsa:To>");
+ httpheader
+ .append("<mobyws:ServiceInvocationId xmlns:mobyws=\"http://biomoby.org/\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsa:IsReferenceParameter=\"true\">"
+ + epr.getServiceInvocationId()
+ + "</mobyws:ServiceInvocationId>");
+ httpheader.append("</moby-wsrf>");
+ method.addRequestHeader("moby-wsrf", httpheader.toString().replaceAll(
+ "\r\n", ""));
+ // retry up to 10 times
+ client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+ new DefaultHttpMethodRetryHandler(10, true));
+
+ // call the method
+ try {
+ int result = client.executeMethod(method);
+ if (result != HttpStatus.SC_OK)
+ throw new MobyException(
+ "Async HTTP POST service returned code: " + result
+ + "\n" + method.getStatusLine());
+ } catch (IOException e) {
+ throw new MobyException("Problem reading response from webservice",
+ e);
+ } finally {
+ // Release current connection to the connection pool once you are
+ // done
+ method.releaseConnection();
+ }
+ }
+
+ /**
+ *
+ * @param endpoint
+ * the url to the service to call
+ * @param xml
+ * the BioMOBY input message
+ * @return EndpointReference the EPR returned by the service
+ * @throws MobyException
+ */
+ private static EndpointReference launchCgiAsyncService(String endpoint,
+ String xml) throws MobyException {
+ // construct the Httpclient
+ HttpClient client = new HttpClient();
+ client.getParams().setParameter("http.useragent", "jMoby/Taverna2");
+ // create the post method
+ PostMethod method = new PostMethod(endpoint);
+
+ // put our data in the request
+ RequestEntity entity;
+ try {
+ entity = new StringRequestEntity(xml, "text/xml", null);
+ } catch (UnsupportedEncodingException e) {
+ throw new MobyException("Problem posting data to webservice", e);
+ }
+ method.setRequestEntity(entity);
+
+ // retry up to 10 times
+ client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+ new DefaultHttpMethodRetryHandler(10, true));
+
+ // call the method
+ try {
+ int result = client.executeMethod(method);
+ if (result != HttpStatus.SC_OK)
+ throw new MobyException(
+ "Async HTTP POST service returned code: " + result
+ + "\n" + method.getStatusLine());
+ return EndpointReference.createFromXML(method.getResponseHeader(
+ "moby-wsrf").getValue());
+ } catch (IOException e) {
+ throw new MobyException("Problem reading response from webservice",
+ e);
+ } finally {
+ // Release current connection to the connection pool once you are
+ // done
+ method.releaseConnection();
+ }
+ }
+
+ private static boolean pollAsyncCgiService(String msName, String url,
+ EndpointReference epr, String[] queryIds, String[] result)
+ throws MobyException {
+ // Needed to remap results
+ HashMap<String, Integer> queryMap = new HashMap<String, Integer>();
+ for (int qi = 0; qi < queryIds.length; qi++) {
+ String queryId = queryIds[qi];
+ if (queryId != null)
+ queryMap.put(queryId, new Integer(qi));
+ }
+
+ if (queryMap.size() == 0)
+ return false;
+
+ // construct the GetMultipleResourceProperties XML
+ StringBuffer xml = new StringBuffer();
+ xml.append("<wsrf-rp:GetMultipleResourceProperties xmlns:wsrf-rp='"
+ + RESOURCE_PROPERTIES_NS
+ + "' xmlns:mobyws='http://biomoby.org/'>");
+ for (String q : queryMap.keySet())
+ xml.append("<wsrf-rp:ResourceProperty>mobyws:" + STATUS_PREFIX + q
+ + "</wsrf-rp:ResourceProperty>");
+ xml.append("</wsrf-rp:GetMultipleResourceProperties>");
+
+ StringBuffer httpheader = new StringBuffer();
+ httpheader.append("<moby-wsrf>");
+ httpheader
+ .append("<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">"
+ + GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION
+ + "</wsa:Action>");
+ httpheader
+ .append("<wsa:To xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsu:Id=\"To\">"
+ + url + "</wsa:To>");
+ httpheader
+ .append("<mobyws:ServiceInvocationId xmlns:mobyws=\"http://biomoby.org/\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsa:IsReferenceParameter=\"true\">"
+ + epr.getServiceInvocationId()
+ + "</mobyws:ServiceInvocationId>");
+ httpheader.append("</moby-wsrf>");
+
+ AnalysisEvent[] l_ae = null;
+ // First, status from queries
+ String response = "";
+ // construct the Httpclient
+ HttpClient client = new HttpClient();
+ client.getParams().setParameter("http.useragent", "jMoby/Taverna2");
+ // create the post method
+ PostMethod method = new PostMethod(url + "/status");
+ // add the moby-wsrf header (with no newlines)
+ method.addRequestHeader("moby-wsrf", httpheader.toString().replaceAll(
+ "\r\n", ""));
+
+ // put our data in the request
+ RequestEntity entity;
+ try {
+ entity = new StringRequestEntity(xml.toString(), "text/xml", null);
+ } catch (UnsupportedEncodingException e) {
+ throw new MobyException("Problem posting data to webservice", e);
+ }
+ method.setRequestEntity(entity);
+
+ // retry up to 10 times
+ client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+ new DefaultHttpMethodRetryHandler(10, true));
+
+ // call the method
+ try {
+ if (client.executeMethod(method) != HttpStatus.SC_OK)
+ throw new MobyException(
+ "Async HTTP POST service returned code: "
+ + method.getStatusCode() + "\n"
+ + method.getStatusLine()
+ + "\nduring our polling request");
+ response = stream2String(method.getResponseBodyAsStream());
+ } catch (IOException e) {
+ throw new MobyException("Problem reading response from webservice",
+ e);
+ } finally {
+ // Release current connection to the connection pool once you
+ // are
+ // done
+ method.releaseConnection();
+ }
+
+ if (response != null) {
+ l_ae = AnalysisEvent.createFromXML(response);
+ }
+
+ if (l_ae == null || l_ae.length == 0) {
+ new MobyException(
+ "Troubles while checking asynchronous MOBY job status from service "
+ + msName);
+ }
+
+ ArrayList<String> finishedQueries = new ArrayList<String>();
+ // Second, gather those finished queries
+ for (int iae = 0; iae < l_ae.length; iae++) {
+ AnalysisEvent ae = l_ae[iae];
+ if (ae.isCompleted()) {
+ String queryId = ae.getQueryId();
+ if (!queryMap.containsKey(queryId)) {
+ throw new MobyException(
+ "Invalid result queryId on asynchronous MOBY job status fetched from "
+ + msName);
+ }
+ finishedQueries.add(queryId);
+ }
+ }
+
+ // Third, let's fetch the results from the finished queries
+ if (finishedQueries.size() > 0) {
+ String[] resQueryIds = finishedQueries.toArray(new String[0]);
+ for (int x = 0; x < resQueryIds.length; x++) {
+ // construct the GetMultipleResourceProperties XML
+ xml = new StringBuffer();
+ xml
+ .append("<wsrf-rp:GetMultipleResourceProperties xmlns:wsrf-rp='"
+ + RESOURCE_PROPERTIES_NS
+ + "' xmlns:mobyws='http://biomoby.org/'>");
+ for (String q : resQueryIds)
+ xml.append("<wsrf-rp:ResourceProperty>mobyws:" + RESULT_PREFIX + q
+ + "</wsrf-rp:ResourceProperty>");
+ xml.append("</wsrf-rp:GetMultipleResourceProperties>");
+
+ httpheader = new StringBuffer();
+ httpheader.append("<moby-wsrf>");
+ httpheader
+ .append("<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">"
+ + GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION
+ + "</wsa:Action>");
+ httpheader
+ .append("<wsa:To xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsu:Id=\"To\">"
+ + url + "</wsa:To>");
+ httpheader
+ .append("<mobyws:ServiceInvocationId xmlns:mobyws=\"http://biomoby.org/\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" wsa:IsReferenceParameter=\"true\">"
+ + epr.getServiceInvocationId()
+ + "</mobyws:ServiceInvocationId>");
+ httpheader.append("</moby-wsrf>");
+ client = new HttpClient();
+ client.getParams().setParameter("http.useragent",
+ "jMoby/Taverna2");
+ // create the post method
+ method = new PostMethod(url + "/results");
+ // add the moby-wsrf header (with no newlines)
+ method.addRequestHeader("moby-wsrf", httpheader.toString()
+ .replaceAll("\r\n", ""));
+
+ // put our data in the request
+ entity = null;
+ try {
+ entity = new StringRequestEntity(xml.toString(),
+ "text/xml", null);
+ } catch (UnsupportedEncodingException e) {
+ throw new MobyException(
+ "Problem posting data to webservice", e);
+ }
+ method.setRequestEntity(entity);
+
+ // retry up to 10 times
+ client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+ new DefaultHttpMethodRetryHandler(10, true));
+
+ // call the method
+ try {
+ if (client.executeMethod(method) != HttpStatus.SC_OK)
+ throw new MobyException(
+ "Async HTTP POST service returned code: "
+ + method.getStatusCode() + "\n"
+ + method.getStatusLine()
+ + "\nduring our polling request");
+ // place the result in the array
+ result[x] = stream2String(method.getResponseBodyAsStream());
+ // Marking as null
+ queryIds[x] = null;
+ } catch (IOException e) {
+ logger.warn("Problem getting result from webservice\n"
+ + e.getMessage());
+ } finally {
+ // Release current connection
+ method.releaseConnection();
+ }
+ }
+
+ }
+ return finishedQueries.size() != queryMap.size();
+ }
+
+ private static String stream2String(InputStream is) {
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+ String line = null;
+ String newline = System.getProperty("line.separator");
+ try {
+ while ((line = br.readLine()) != null) {
+ sb.append(line + newline);
+ }
+ } catch (IOException e) {
+ logger.warn("Exception reading input stream ...", e);
+ } finally {
+ try {
+ br.close();
+ } catch (IOException e) {
+ logger.warn("Exception closing input stream ...", e);
+ }
+ }
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncMobyService.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncMobyService.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncMobyService.java
new file mode 100644
index 0000000..10c76bc
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteAsyncMobyService.java
@@ -0,0 +1,695 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.apache.log4j.Logger;
+import org.biomoby.shared.MobyException;
+import org.biomoby.shared.MobyPrefixResolver;
+import org.biomoby.shared.MobyService;
+import org.biomoby.shared.parser.MobyTags;
+import org.biomoby.w3c.addressing.EndpointReference;
+import org.omg.lsae.notifications.AnalysisEvent;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+
+/**
+ * This class contains one method that is used to execute asynchronous moby
+ * services
+ *
+ * @author Edward Kawas
+ *
+ */
+
+public class ExecuteAsyncMobyService {
+
+ /* async constants */
+ private static final String GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION = "http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest";
+ private static final String DESTROY_RESOURCE_ACTION = "http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyRequest";
+
+ private static final String RESOURCE_PROPERTIES_NS = "http://docs.oasis-open.org/wsrf/rp-2";
+ private static final String RESOURCE_LIFETIME_NS = "http://docs.oasis-open.org/wsrf/rl-2";
+
+ @SuppressWarnings("unused")
+ private static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/";
+ private static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
+ private static final String WSA_NS = "http://www.w3.org/2005/08/addressing";
+ private static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+ private static final String ANON_URI = WSA_NS + "/anonymous";
+ private static final String RESULT_PREFIX = "result_";
+ private static final String STATUS_PREFIX = "status_";
+
+ private static Logger logger = Logger.getLogger(ExecuteAsyncMobyService.class);
+ /**
+ * This method does the same as getMultipleResourceProperties, with the
+ * difference that it returns an String instead of a SOAPPart object. The
+ * result is the serialization of the SOAPPart output obtained from
+ * getMultipleResourceProperties.
+ *
+ * @param msName
+ * The MOBY service name
+ * @param queryIds
+ * The array with the queryIds to use. It may contain null
+ * strings
+ * @param epr
+ * The EndpointReference object which helds the MOBY asynchronous
+ * job information
+ * @param asResult
+ * If this parameter is true, then this call fetches the results
+ * associated to the input queryIds. If it is false, then this
+ * call only asks for the job status.
+ * @return When at least one of the strings from queryIds array was not
+ * null, an String with the serialized answer from the service.
+ * Otherwise, it returns null.
+ * @throws SOAPException
+ */
+ private static String getMultipleResourcePropertiesAsString(String msName,
+ String[] queryIds, EndpointReference epr, boolean asResult)
+ throws TransformerConfigurationException, SOAPException,
+ TransformerException {
+ SOAPPart result = getMultipleResourceProperties(msName, queryIds, epr,
+ asResult);
+ if (result == null)
+ return null;
+ Transformer tr = TransformerFactory.newInstance().newTransformer();
+ tr.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+
+ DOMSource dombody = new DOMSource(result);
+
+ StringWriter sw = new StringWriter();
+ tr.transform(dombody, new StreamResult(sw));
+
+ return sw.toString();
+ }
+
+ /**
+ * This method does the check and fetch work related to asynchronous
+ * services. When all the results are fetched, it returns false. When some
+ * recheck must be issued, it returns true.
+ *
+ * @param msName
+ * The MOBY service name
+ * @param epr
+ * The EndpointReference, used for the queries
+ * @param queryIds
+ * The array which holds the queryIds to ask for. It can contain
+ * null strings.
+ * @param result
+ * The array which will hold the mobyData results. This one must
+ * have the same size as queryIds array.
+ * @return true, if we need more checking iterations. Otherwise, false
+ * @throws MobyException
+ */
+ private static boolean checkMobyAsyncJobsStatus(String msName,
+ EndpointReference epr, String[] queryIds,
+ org.w3c.dom.Element[] result) throws MobyException {
+ // Needed to remap results
+ HashMap<String, Integer> queryMap = new HashMap<String, Integer>();
+ for (int qi = 0; qi < queryIds.length; qi++) {
+ String queryId = queryIds[qi];
+ if (queryId != null)
+ queryMap.put(queryId, new Integer(qi));
+ }
+
+ if (queryMap.size() == 0)
+ return false;
+
+ try {
+ AnalysisEvent[] l_ae = null;
+ // First, status from queries
+ String response = getMultipleResourcePropertiesAsString(msName,
+ queryIds, epr, false);
+ if (response != null) {
+ l_ae = AnalysisEvent.createFromXML(response);
+ }
+
+ if (l_ae == null || l_ae.length == 0) {
+ new MobyException(
+ "Troubles while checking asynchronous MOBY job status from service "
+ + msName);
+ }
+
+ ArrayList<String> finishedQueries = new ArrayList<String>();
+ // Second, gather those finished queries
+ for (int iae = 0; iae < l_ae.length; iae++) {
+ AnalysisEvent ae = l_ae[iae];
+ if (ae.isCompleted()) {
+ String queryId = ae.getQueryId();
+ if (!queryMap.containsKey(queryId)) {
+ throw new MobyException(
+ "Invalid result queryId on asynchronous MOBY job status fetched from "
+ + msName);
+ }
+ finishedQueries.add(queryId);
+ }
+ }
+
+ // Third, let's fetch the results from the finished queries
+ if (finishedQueries.size() > 0) {
+ String[] resQueryIds = finishedQueries.toArray(new String[0]);
+ SOAPPart soapDOM = getMultipleResourceProperties(msName,
+ resQueryIds, epr, true);
+ NodeList l_mul = soapDOM.getElementsByTagNameNS(
+ RESOURCE_PROPERTIES_NS,
+ "GetMultipleResourcePropertiesResponse");
+ if (l_mul == null || l_mul.getLength() == 0) {
+ throw new MobyException(
+ "Error while fetching asynchronous MOBY results from "
+ + msName);
+ }
+
+ org.w3c.dom.Element mul = (org.w3c.dom.Element) l_mul.item(0);
+ for (org.w3c.dom.Node child = mul.getFirstChild(); child != null; child = child
+ .getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE
+ && MobyService.BIOMOBY_SERVICE_URI.equals(child
+ .getNamespaceURI())) {
+ String preQueryId = child.getLocalName();
+ int subpos = preQueryId.indexOf(RESULT_PREFIX);
+ if (subpos != 0) {
+ throw new MobyException(
+ "Invalid result prefix on asynchronous MOBY job results fetched from "
+ + msName);
+ }
+ String queryId = preQueryId.substring(RESULT_PREFIX
+ .length());
+ if (!queryMap.containsKey(queryId)) {
+ throw new MobyException(
+ "Invalid result queryId on asynchronous MOBY job results fetched from "
+ + msName);
+ }
+
+ org.w3c.dom.Element elchild = (org.w3c.dom.Element) child;
+ NodeList l_moby = elchild.getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE,
+ MobyTags.MOBYDATA);
+ if (l_moby == null || l_moby.getLength() == 0)
+ l_moby = elchild
+ .getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE_INVALID,
+ MobyTags.MOBYDATA);
+
+ if (l_moby == null || l_moby.getLength() == 0) {
+ throw new MobyException(
+ "Recovered empty payload from asynchronous MOBY service "
+ + msName);
+ }
+ Integer queryPos = queryMap.get(queryId);
+ result[queryPos] = (org.w3c.dom.Element) l_moby.item(0);
+ // Marking as null
+ queryIds[queryPos] = null;
+ }
+ }
+ }
+
+ return finishedQueries.size() != queryMap.size();
+ } catch (SOAPException se) {
+ throw new MobyException("Error while querying MOBY job status", se);
+ } catch (TransformerConfigurationException tce) {
+ throw new MobyException(
+ "Error while preparing to parse MOBY job status", tce);
+ } catch (TransformerException te) {
+ throw new MobyException("Error while parsing MOBY job status", te);
+ }
+ }
+
+ /**
+ * This method calls the input MOBY service using the asynchronous protocol.
+ *
+ * @param endpoint
+ * The endpoint of the service.
+ * @param msName
+ * The MOBY service name.
+ * @param mobyXML
+ * The MOBY payload to be sent to the service.
+ * @return The MOBY payload with the results from the service.
+ * @throws MobyException
+ */
+ public static String executeMobyAsyncService(String endpoint, String msName,
+ String mobyXML) throws MobyException {
+ // First, let's get the queryIds
+ org.w3c.dom.Document message = null;
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ message = db.parse(new InputSource(new StringReader(mobyXML)));
+ } catch (Throwable t) {
+ throw new MobyException("Error while parsing input query", t);
+ }
+
+ NodeList l_data = message.getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE, MobyTags.MOBYDATA);
+ if (l_data == null || l_data.getLength() == 0) {
+ l_data = message.getElementsByTagNameNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE_INVALID,
+ MobyTags.MOBYDATA);
+ }
+
+ // Freeing resources
+ message = null;
+
+ if (l_data == null || l_data.getLength() == 0) {
+ throw new MobyException("Empty asynchronous MOBY query!");
+ }
+
+ int nnode = l_data.getLength();
+ String[] queryIds = new String[nnode];
+ String[] tmpQueryIds = new String[nnode];
+ org.w3c.dom.Element[] results = new org.w3c.dom.Element[nnode];
+ for (int inode = 0; inode < nnode; inode++) {
+ String queryId = null;
+
+ org.w3c.dom.Element mdata = (org.w3c.dom.Element) l_data
+ .item(inode);
+
+ queryId = mdata.getAttribute(MobyTags.QUERYID);
+ if (queryId == null || queryId.length() == 0)
+ queryId = mdata
+ .getAttributeNS(MobyPrefixResolver.MOBY_XML_NAMESPACE,
+ MobyTags.QUERYID);
+ if (queryId == null || queryId.length() == 0)
+ queryId = mdata.getAttributeNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE_INVALID,
+ MobyTags.QUERYID);
+
+ if (queryId == null || queryId.length() == 0) {
+ throw new MobyException(
+ "Unable to extract queryId for outgoing MOBY message");
+ }
+
+ tmpQueryIds[inode] = queryIds[inode] = queryId;
+ results[inode] = null;
+ }
+
+ // Freeing resources
+ l_data = null;
+
+ // Second, let's launch
+ EndpointReference epr = launchMobyAsyncService(endpoint, msName,
+ mobyXML);
+
+ // Third, waiting for the results
+ try {
+ // FIXME - add appropriate values here
+ long pollingInterval = 1000L; // proc.getRetryDelay();
+ double backoff = 1.0;// proc.getBackoff();
+
+ // Max: one minute pollings
+ long maxPollingInterval = 60000L;
+
+ // Min: one second
+ if (pollingInterval <= 0L)
+ pollingInterval = 1000L;
+
+ // Backoff: must be bigger than 1.0
+ if (backoff <= 1.0)
+ backoff = 1.5;
+
+ do {
+ try {
+ Thread.sleep(pollingInterval);
+ } catch (InterruptedException ie) {
+ // DoNothing(R)
+ }
+
+ if (pollingInterval != maxPollingInterval) {
+ pollingInterval = (long) ((double) pollingInterval * backoff/*
+ * proc.
+ * getBackoff
+ * (
+ * )
+ */);
+ if (pollingInterval > maxPollingInterval) {
+ pollingInterval = maxPollingInterval;
+ }
+ }
+ } while (checkMobyAsyncJobsStatus(msName, epr, tmpQueryIds, results));
+ } finally {
+ try {
+ freeAsyncResources(msName, epr);
+ } catch (SOAPException se) {
+ logger.info(
+ "An error was fired while freeing MOBY asynchronous resources from "
+ + msName, se);
+ }
+ }
+
+ // Fourth, assembling back the results
+ org.w3c.dom.Document resdoc = null;
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ resdoc = db.newDocument();
+
+ org.w3c.dom.Element mobyroot = resdoc.createElementNS(
+ MobyPrefixResolver.MOBY_XML_NAMESPACE, MobyTags.MOBY);
+ resdoc.appendChild(mobyroot);
+ org.w3c.dom.Element mobycontent = resdoc
+ .createElementNS(MobyPrefixResolver.MOBY_XML_NAMESPACE,
+ MobyTags.MOBYCONTENT);
+ mobyroot.appendChild(mobycontent);
+
+ // Results array already contains mobyData
+
+ for (org.w3c.dom.Element result : results) {
+ mobycontent.appendChild(resdoc.importNode(result, true));
+ }
+ } catch (Throwable t) {
+ throw new MobyException("Error while assembling output", t);
+ }
+
+ // Fifth, returning results
+ try {
+ Transformer tr = TransformerFactory.newInstance().newTransformer();
+ tr.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+
+ DOMSource dombody = new DOMSource(resdoc);
+
+ StringWriter sw = new StringWriter();
+ tr.transform(dombody, new StreamResult(sw));
+
+ return sw.toString();
+ } catch (Throwable t) {
+ throw new MobyException("Error while assembling output", t);
+ }
+ }
+
+ /**
+ * This method free the asynchronous MOBY resources associated to the job
+ * identifier tied to the EndpointReference object passed as input.
+ *
+ * @param msName
+ * The MOBY service name
+ * @param epr
+ * The EndpointReference object which holds the MOBY asynchronous
+ * job information
+ * @throws SOAPException
+ */
+ private static void freeAsyncResources(String msName, EndpointReference epr)
+ throws SOAPException {
+ Service service = Service.create(new QName(
+ MobyService.BIOMOBY_SERVICE_URI, msName + "Service"));
+ QName mQName = new QName(MobyService.BIOMOBY_SERVICE_URI,
+ "WSRF_Operations_Port");
+ service.addPort(mQName, SOAPBinding.SOAP11HTTP_BINDING, epr
+ .getAddress());
+
+ Dispatch<SOAPMessage> dispatch = service.createDispatch(mQName,
+ SOAPMessage.class, Service.Mode.MESSAGE);
+ Map<String, Object> rc = dispatch.getRequestContext();
+ rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, new Boolean(true));
+ rc.put(BindingProvider.SOAPACTION_URI_PROPERTY,
+ GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION);
+
+ MessageFactory mf = MessageFactory.newInstance();
+ SOAPMessage request = mf.createMessage();
+ SOAPPart part = request.getSOAPPart();
+
+ String mobyPrefix = "mobyws";
+ String wsaPrefix = "wsa";
+ String wsuPrefix = "wsu";
+ // Obtain the SOAPEnvelope and header and body elements.
+ SOAPEnvelope env = part.getEnvelope();
+ SOAPHeader header = env.getHeader();
+ SOAPBody body = env.getBody();
+
+ header.addNamespaceDeclaration(mobyPrefix,
+ MobyService.BIOMOBY_SERVICE_URI);
+ header.addNamespaceDeclaration(wsaPrefix, WSA_NS);
+ header.addNamespaceDeclaration(wsuPrefix, WSU_NS);
+ // This is for the action
+ SOAPElement actionRoot = header.addChildElement("Action", wsaPrefix,
+ WSA_NS);
+ actionRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS),
+ "Action");
+ actionRoot.addTextNode(DESTROY_RESOURCE_ACTION);
+
+ // This is for the To
+ SOAPElement toRoot = header.addChildElement("To", wsaPrefix, WSA_NS);
+ toRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS), "To");
+ toRoot.addTextNode(epr.getAddress());
+
+ // And this is for the mobyws
+ SOAPElement mobywsRoot = header.addChildElement("ServiceInvocationId",
+ mobyPrefix, MobyService.BIOMOBY_SERVICE_URI);
+ mobywsRoot.addNamespaceDeclaration(wsaPrefix, WSA_NS);
+ mobywsRoot.addAttribute(env.createName("isReferenceParameter",
+ wsaPrefix, WSA_NS), "true");
+ mobywsRoot.addTextNode(epr.getServiceInvocationId());
+
+ // At last, the replyto
+ SOAPElement replyRoot = header.addChildElement("ReplyTo", wsaPrefix,
+ WSA_NS);
+ replyRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS),
+ "ReplyTo");
+ SOAPElement addr = replyRoot.addChildElement("Address", wsaPrefix,
+ WSA_NS);
+ addr.addTextNode(ANON_URI);
+
+ // Let's disable the headers
+ // ((WSBindingProvider)dispatch).setOutboundHeaders(headers);
+
+ // Now the SOAP body
+ body.addChildElement("Destroy", "rl", RESOURCE_LIFETIME_NS);
+
+ request.saveChanges();
+ // We don't mind what it is returned
+ dispatch.invoke(request);
+ }
+
+ /**
+ * This method is used to launch an asynchronous MOBY job.
+ *
+ * @param endpoint
+ * The endpoint of the service.
+ * @param msName
+ * The MOBY service name.
+ * @param mobyXML
+ * The MOBY payload to be sent to the service.
+ * @return The EndpointReference object which helds the details of the MOBY
+ * asynchronous job.
+ * @throws MobyException
+ */
+ private static EndpointReference launchMobyAsyncService(String endpoint,
+ String msName, String mobyXML) throws MobyException {
+ try {
+ Service service = Service.create(new QName(
+ MobyService.BIOMOBY_SERVICE_URI, msName + "Service"));
+ QName mQName = new QName(MobyService.BIOMOBY_SERVICE_URI, msName
+ + "Port");
+
+ service.addPort(mQName, SOAPBinding.SOAP11HTTP_BINDING, endpoint);
+ Dispatch<SOAPMessage> dispatch = service.createDispatch(mQName,
+ SOAPMessage.class, Service.Mode.MESSAGE);
+ Map<String, Object> rc = dispatch.getRequestContext();
+ rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, new Boolean(true));
+ rc.put(BindingProvider.SOAPACTION_URI_PROPERTY,
+ MobyService.BIOMOBY_SERVICE_URI + "#" + msName + "_submit");
+
+ MessageFactory mf = MessageFactory.newInstance();
+ SOAPMessage request = mf.createMessage();
+ SOAPPart part = request.getSOAPPart();
+
+ String mobyPrefix = "mobyws";
+ String xsiPrefix = "xsi";
+
+ // Obtain the SOAPEnvelope and header and body elements.
+ SOAPEnvelope env = part.getEnvelope();
+ SOAPBody body = env.getBody();
+
+ // Now the SOAP body
+ body.addNamespaceDeclaration(mobyPrefix,
+ MobyService.BIOMOBY_SERVICE_URI);
+ SOAPElement rootMessage = body.addChildElement(msName + "_submit",
+ mobyPrefix, MobyService.BIOMOBY_SERVICE_URI);
+ SOAPElement data = rootMessage.addChildElement("data", mobyPrefix,
+ MobyService.BIOMOBY_SERVICE_URI);
+ data.addNamespaceDeclaration(xsiPrefix,
+ MobyPrefixResolver.XSI_NAMESPACE2001);
+ data.addNamespaceDeclaration("xsd", XSD_NS);
+ data.addAttribute(env.createName("type", xsiPrefix,
+ MobyPrefixResolver.XSI_NAMESPACE2001), "xsd:string");
+ data.addTextNode(mobyXML);
+
+ request.saveChanges();
+ SOAPMessage outputMessage = dispatch.invoke(request);
+ DOMSource output = new DOMSource(outputMessage.getSOAPPart()
+ .getEnvelope());
+
+ StringWriter sw = new StringWriter();
+ Transformer tr = TransformerFactory.newInstance().newTransformer();
+ tr.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ tr.transform(output, new StreamResult(sw));
+
+ String response = sw.toString();
+ return EndpointReference.createFromXML(response);
+ } catch (SOAPException pce) {
+ throw new MobyException(
+ "Unable to create SOAP document builder for MOBY asynchronous call submission",
+ pce);
+ } catch (TransformerConfigurationException tce) {
+ throw new MobyException(
+ "Unable to create transformer factory for MOBY asynchronous call response",
+ tce);
+ } catch (TransformerException te) {
+ throw new MobyException(
+ "Unable to create transformer for MOBY asynchronous call response",
+ te);
+ }
+ }
+
+
+
+ /**
+ * This method issues WSRF getMultipleResourceProperties calls. As this call
+ * is used in BioMOBY for polling and for result fetching, it has an
+ * additional parameter which handles the call mode.
+ *
+ * @param msName
+ * The MOBY service name
+ * @param queryIds
+ * The array with the queryIds to use. It may contain null
+ * strings
+ * @param epr
+ * The EndpointReference object which helds the MOBY asynchronous
+ * job information
+ * @param asResult
+ * If this parameter is true, then this call fetches the results
+ * associated to the input queryIds. If it is false, then this
+ * call only asks for the job status.
+ * @return When at least one of the strings from queryIds array was not
+ * null, a SOAPPart object is returned with the answer for the
+ * request issued to the MOBY service. Otherwise, it returns null.
+ * @throws SOAPException
+ */
+ private static SOAPPart getMultipleResourceProperties(String msName,
+ String[] queryIds, EndpointReference epr, boolean asResult)
+ throws SOAPException {
+ String op = asResult ? RESULT_PREFIX : STATUS_PREFIX;
+
+ Service service = Service.create(new QName(
+ MobyService.BIOMOBY_SERVICE_URI, msName + "Service"));
+ QName mQName = new QName(MobyService.BIOMOBY_SERVICE_URI,
+ "WSRF_Operations_Port");
+ service.addPort(mQName, SOAPBinding.SOAP11HTTP_BINDING, epr
+ .getAddress());
+
+ Dispatch<SOAPMessage> dispatch = service.createDispatch(mQName,
+ SOAPMessage.class, Service.Mode.MESSAGE);
+ Map<String, Object> rc = dispatch.getRequestContext();
+ rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, new Boolean(true));
+ rc.put(BindingProvider.SOAPACTION_URI_PROPERTY,
+ GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION);
+
+ MessageFactory mf = MessageFactory.newInstance();
+ SOAPMessage request = mf.createMessage();
+ SOAPPart part = request.getSOAPPart();
+
+ String mobyPrefix = "mobyws";
+ String wsaPrefix = "wsa";
+ String wsuPrefix = "wsu";
+ // Obtain the SOAPEnvelope and header and body elements.
+ SOAPEnvelope env = part.getEnvelope();
+ SOAPHeader header = env.getHeader();
+ SOAPBody body = env.getBody();
+
+ header.addNamespaceDeclaration(mobyPrefix,
+ MobyService.BIOMOBY_SERVICE_URI);
+ header.addNamespaceDeclaration(wsaPrefix, WSA_NS);
+ header.addNamespaceDeclaration(wsuPrefix, WSU_NS);
+ // This is for the action
+ SOAPElement actionRoot = header.addChildElement("Action", wsaPrefix,
+ WSA_NS);
+ actionRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS),
+ "Action");
+ actionRoot.addTextNode(GET_MULTIPLE_RESOURCE_PROPERTIES_ACTION);
+
+ // This is for the To
+ SOAPElement toRoot = header.addChildElement("To", wsaPrefix, WSA_NS);
+ toRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS), "To");
+ toRoot.addTextNode(epr.getAddress());
+
+ // And this is for the mobyws
+ SOAPElement mobywsRoot = header.addChildElement("ServiceInvocationId",
+ mobyPrefix, MobyService.BIOMOBY_SERVICE_URI);
+ mobywsRoot.addNamespaceDeclaration(wsaPrefix, WSA_NS);
+ mobywsRoot.addAttribute(env.createName("isReferenceParameter",
+ wsaPrefix, WSA_NS), "true");
+ mobywsRoot.addTextNode(epr.getServiceInvocationId());
+
+ // At last, the replyto
+ SOAPElement replyRoot = header.addChildElement("ReplyTo", wsaPrefix,
+ WSA_NS);
+ replyRoot.addAttribute(env.createName("Id", wsuPrefix, WSU_NS),
+ "ReplyTo");
+ SOAPElement addr = replyRoot.addChildElement("Address", wsaPrefix,
+ WSA_NS);
+ addr.addTextNode(ANON_URI);
+
+ // Let's disable the headers
+ // ((WSBindingProvider)dispatch).setOutboundHeaders(headers);
+
+ // Now the SOAP body
+ SOAPElement smrp = body.addChildElement(
+ "GetMultipleResourceProperties", "rp", RESOURCE_PROPERTIES_NS);
+ boolean doSubmit = false;
+ for (String queryId : queryIds) {
+ if (queryId != null) {
+ doSubmit = true;
+ SOAPElement sii = smrp.addChildElement("ResourceProperty",
+ "rp", RESOURCE_PROPERTIES_NS);
+ sii.addNamespaceDeclaration(mobyPrefix,
+ MobyService.BIOMOBY_SERVICE_URI);
+ sii.addTextNode(mobyPrefix + ":" + op + queryId);
+ }
+ }
+
+ if (doSubmit) {
+ request.saveChanges();
+ SOAPMessage output = dispatch.invoke(request);
+
+ return output.getSOAPPart();
+ } else {
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteCgiService.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteCgiService.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteCgiService.java
new file mode 100644
index 0000000..a221a8a
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteCgiService.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+
+import org.biomoby.shared.MobyException;
+
+/**
+ * This class contains one method that is used to execute synchronous HTTP POST
+ * services
+ *
+ * @author Edward Kawas
+ *
+ */
+
+public class ExecuteCgiService {
+
+ /**
+ *
+ * @param serviceEndpoint
+ * the URL to the HTTP POST service
+ * @param xml
+ * the XML to send the service
+ * @return a string representing the output from the service
+ * @throws MobyException
+ * if anything goes wrong (problems reading/writing to the
+ * service)
+ */
+ public static String executeCgiService(String serviceEndpoint, String xml)
+ throws MobyException {
+ try {
+ // Construct data
+ String data = "data=" + URLEncoder.encode(xml, "UTF-8");
+
+ // Send data
+ URL url = new URL(serviceEndpoint);
+ URLConnection conn = url.openConnection();
+ conn.setDoOutput(true);
+ OutputStreamWriter wr = new OutputStreamWriter(conn
+ .getOutputStream());
+ wr.write(data);
+ wr.flush();
+ // Get the response
+ BufferedReader rd = new BufferedReader(new InputStreamReader(conn
+ .getInputStream()));
+ String line;
+ StringBuffer sb = new StringBuffer();
+ while ((line = rd.readLine()) != null) {
+ sb.append(line);
+ }
+ wr.close();
+ rd.close();
+ return sb.toString();
+ } catch (Exception e) {
+ throw new MobyException(e.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteMobyService.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteMobyService.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteMobyService.java
new file mode 100644
index 0000000..f494d47
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ExecuteMobyService.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import org.biomoby.client.CentralImpl;
+import org.biomoby.shared.MobyException;
+
+/**
+ * This class contains one method that is used to execute synchronous moby
+ * services
+ *
+ * @author Edward Kawas
+ *
+ */
+
+public class ExecuteMobyService {
+
+ /**
+ *
+ * @param endpoint
+ * the SOAP endpoint of the service to call
+ * @param service
+ * the name of the service
+ * @param xml
+ * the XML to send the service
+ * @return a string of XML representing the output from the service given
+ * our input
+ * @throws MobyException
+ * if anything goes wrong (SOAP error)
+ */
+ public static String executeMobyService(String endpoint, String service,
+ String xml) throws MobyException {
+ return new CentralImpl(endpoint, "http://biomoby.org/").call(service,
+ xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/GetOntologyThread.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/GetOntologyThread.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/GetOntologyThread.java
new file mode 100644
index 0000000..e2402e8
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/GetOntologyThread.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+/*
+ * This file is a component of the Taverna project,
+ * and is licensed under the GNU LGPL.
+ * Copyright Edward Kawas, The BioMoby Project
+ */
+
+package net.sf.taverna.t2.activities.biomoby;
+
+
+import org.biomoby.client.CentralImpl;
+
+/**
+ * This class is used to speed up the running of workflows. Basically, whenever
+ * a new Biomoby activity is added to taverna, a call out to RESOURCES/Objects
+ * is made to download the datatype ontology.
+ *
+ * Uses BiomobyCache to process the registry
+ *
+ * This should speed up the execution of workflows, since the ontologies will
+ * have already been downloaded.
+ *
+ * @author Eddie Kawas
+ * @author Stuart Owen
+ *
+ * @see BiomobyCache
+ *
+ */
+public class GetOntologyThread extends Thread {
+
+
+ // the registry endpoint
+ String worker = null;
+
+ /**
+ *
+ * @param url
+ * the registry endpoint URL
+ */
+ public GetOntologyThread(String url) {
+ super("BioMOBY GetOntologyThread");
+ if (url == null || url.trim().equals(""))
+ url = CentralImpl.getDefaultURL();
+ this.worker = url;
+ setDaemon(true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Thread#run()
+ */
+ public void run() {
+ BiomobyCache.cacheForRegistryEndpoint(worker);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivity.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivity.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivity.java
new file mode 100644
index 0000000..c33a5bf
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivity.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+
+import net.sf.taverna.t2.annotation.annotationbeans.MimeType;
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+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.EditException;
+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 org.apache.log4j.Logger;
+import org.biomoby.client.CentralImpl;
+import org.biomoby.shared.Central;
+import org.biomoby.shared.MobyDataType;
+import org.biomoby.shared.MobyException;
+import org.biomoby.shared.MobyRelationship;
+import org.biomoby.shared.NoSuccessException;
+
+/**
+ * An Activity that breaks up a Moby datatype into its component parts minus all
+ * the moby wrappings.
+ *
+ * Copied from org.biomoby.client.taverna.plugin.MobyParseDatatypeActivityProcessor and
+ * org.biomoby.client.taverna.plugin.MobyParseDatatypeActivityTask and converted to a Taverna 2
+ * Activity.
+ *
+ * @author Edward Kawas
+ * @author David Withers
+ */
+public class MobyParseDatatypeActivity extends AbstractAsynchronousActivity<MobyParseDatatypeActivityConfigurationBean> {
+
+ public static final String URI = "http://ns.taverna.org.uk/2010/activity/biomoby/parser";
+
+ private static Logger logger = Logger.getLogger(MobyParseDatatypeActivity.class);
+
+ private MobyParseDatatypeActivityConfigurationBean configurationBean = new MobyParseDatatypeActivityConfigurationBean();
+
+ private Central central = null;
+
+ private MobyDataType datatype = null;
+
+ @Override
+ public void configure(MobyParseDatatypeActivityConfigurationBean configurationBean) throws ActivityConfigurationException {
+ this.configurationBean = configurationBean;
+ init();
+ }
+
+ @Override
+ public void executeAsynch(final Map<String, T2Reference> data,
+ final AsynchronousActivityCallback callback) {
+ callback.requestRun(new Runnable() {
+
+ @SuppressWarnings("unchecked")
+ public void run() {
+ ReferenceService referenceService = callback.getContext().getReferenceService();
+
+ Map<String, T2Reference> output = new HashMap<String, T2Reference>();
+
+ try {
+
+ //cache ontology and namespace if not done so already. Immediately returns if already cached.
+ BiomobyCache.cacheForRegistryEndpoint(getConfiguration().getRegistryEndpoint());
+
+ String inputMapKey = getInputPorts().iterator().next().getName();
+ // inputMap wasnt as expected
+ if (!data.containsKey(inputMapKey)) {
+ callback.receiveResult(output, new int[0]);
+ return;
+ }
+
+ T2Reference inputId = data.get(inputMapKey);
+
+ Object input = referenceService.renderIdentifier(inputId, String.class, callback.getContext());
+
+ if (input instanceof String) {
+ //logger.error(inputMapKey + " is a string!\n");
+ String inputXML = (String) input;
+ for (OutputPort outPort : getOutputPorts()) {
+ String outputPortName = outPort.getName();
+ String[] invocations = XMLUtilities.getSingleInvokationsFromMultipleInvokations(inputXML);
+ ArrayList<String> names = new ArrayList<String>();
+ int type = 0;
+ // get the type, names list, etc
+ if (outputPortName.equalsIgnoreCase("namespace")) {
+ // extract the namespace from the top element
+ names.add(configurationBean.getArticleNameUsedByService());
+ type = ParseMobyXML.NAMESPACE;
+ } else if (outputPortName.equalsIgnoreCase("id")) {
+ // extract the id from the top element
+ names.add(configurationBean.getArticleNameUsedByService());
+ type = ParseMobyXML.ID;
+ } else {
+ names = getNames(outputPortName);
+ if (outputPortName.endsWith("_ns")) {
+ type = ParseMobyXML.NAMESPACE;
+ if (names.size() > 1) // added nov15-2007
+ names.remove(names.size()-1);
+ } else if (outputPortName.endsWith("_id")) {
+ type = ParseMobyXML.ID;
+ if (names.size() > 1)//added nov15-2007
+ names.remove(names.size()-1);
+ } else {
+ type = ParseMobyXML.VALUE;
+ }
+ }
+ ArrayList<String> stuff = new ArrayList<String>();
+ for (int i = 0; i < invocations.length; i++) {
+ String invocation = invocations[i];
+ if (XMLUtilities.isCollection(invocation)) {
+ String[] simples = XMLUtilities.getAllSimplesByArticleName(configurationBean.getArticleNameUsedByService(), invocation);
+ for (int j = 0; j < simples.length; j++) {
+ ArrayList<String> content = ParseMobyXML.getContentForDataType(names, type, XMLUtilities.createMobyDataElementWrapper(simples[j],"a1", null), configurationBean.getRegistryEndpoint());
+ stuff.addAll(content);
+ }
+ } else {
+ ArrayList<String> content = ParseMobyXML.getContentForDataType(names, type, invocations[i],configurationBean.getRegistryEndpoint());
+ stuff.addAll(content);
+ }
+ }
+ output.put(outputPortName, referenceService.register(stuff, 1, true, callback.getContext()));
+ }
+
+ } else if (input instanceof List) {
+ //logger.error(inputMapKey + " is a list!\n");
+ List<String> list = (List) input;
+ // holder contains a list of strings indexed by output port name
+ // TODO put stuff in the map and in the end put it in the output map
+ HashMap<String, ArrayList<String>> holder = new HashMap<String, ArrayList<String>>();
+ for (Iterator<String> it = list.iterator(); it.hasNext();) {
+ String inputXML = (String) it.next();
+ for (OutputPort outPort : getOutputPorts()) {
+ String outputPortName = outPort.getName();
+ String[] invocations = XMLUtilities.getSingleInvokationsFromMultipleInvokations(inputXML);
+ ArrayList<String> names = new ArrayList<String>();
+ int type = 0;
+ // get the type, names list, etc
+ if (outputPortName.equalsIgnoreCase("namespace")) {
+ // extract the namespace from the top element
+ names.add(configurationBean.getArticleNameUsedByService());
+ type = ParseMobyXML.NAMESPACE;
+ } else if (outputPortName.equalsIgnoreCase("id")) {
+ // extract the id from the top element
+ names.add(configurationBean.getArticleNameUsedByService());
+ type = ParseMobyXML.ID;
+ } else {
+ names = getNames(outputPortName);
+ if (outputPortName.endsWith("_ns")) {
+ type = ParseMobyXML.NAMESPACE;
+ if (names.size() > 1)//added nov-15-07
+ names.remove(names.size()-1);
+ } else if (outputPortName.endsWith("_id")) {
+ type = ParseMobyXML.ID;
+ if (names.size() > 1)//added nov-15-07
+ names.remove(names.size()-1);
+ } else {
+ type = ParseMobyXML.VALUE;
+ }
+ }
+ ArrayList<String> stuff = new ArrayList<String>();
+ for (int i = 0; i < invocations.length; i++) {
+ String invocation = invocations[i];
+ if (XMLUtilities.isCollection(invocation)) {
+ String[] simples = XMLUtilities.getAllSimplesByArticleName(configurationBean.getArticleNameUsedByService(), invocation);
+ for (int j = 0; j < simples.length; j++) {
+ ArrayList<String> content = ParseMobyXML.getContentForDataType(names, type, XMLUtilities.createMobyDataElementWrapper(simples[j],"a1", null),configurationBean.getRegistryEndpoint());
+ stuff.addAll(content);
+ }
+ } else {
+ ArrayList<String> content = ParseMobyXML.getContentForDataType(names, type, invocations[i],configurationBean.getRegistryEndpoint());
+ stuff.addAll(content);
+ }
+ }
+ if (holder.containsKey(outputPortName)) {
+ ArrayList<String> al = holder.get(outputPortName);
+ al.addAll(stuff);
+ holder.put(outputPortName, al);
+ } else {
+ holder.put(outputPortName, stuff);
+ }
+ }
+ }
+ // fill output map
+ for (Iterator<String> it = holder.keySet().iterator(); it.hasNext();) {
+ String key = it.next();
+ output.put(key, referenceService.register(holder.get(key), 1, true, callback.getContext()));
+ }
+ }
+
+ callback.receiveResult(output, new int[0]);
+ } catch (ReferenceServiceException e) {
+ callback.fail("Error accessing input/output data", e);
+ } catch (Exception e) {
+ callback.fail("rror parsing moby data", e);
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public MobyParseDatatypeActivityConfigurationBean getConfiguration() {
+ return configurationBean;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void init() throws ActivityConfigurationException {
+ try {
+ central = new CentralImpl(configurationBean.getRegistryEndpoint());
+ } catch (MobyException e) {
+ throw new ActivityConfigurationException("Couldn't create MobyCentral client for endpoint "
+ + configurationBean.getRegistryEndpoint() + System.getProperty("line.separator")
+ + e.getLocalizedMessage());
+ }
+ if (this.datatype == null) {
+ try {
+ this.datatype = central.getDataType(configurationBean.getDatatypeName());
+ } catch (MobyException e) {
+ throw new ActivityConfigurationException(
+ "There was a problem getting information from the MobyCentral registry at "
+ + configurationBean.getRegistryEndpoint() + System.getProperty("line.separator")
+ + e.getLocalizedMessage());
+ } catch (NoSuccessException e) {
+ throw new ActivityConfigurationException(
+ "There was no success in getting information from the MobyCentral registry at "
+ + configurationBean.getRegistryEndpoint() + System.getProperty("line.separator")
+ + e.getLocalizedMessage());
+ }
+ }
+
+// setDescription("Service to parse the datatype " + this.datatype.getName());
+
+ ArrayList list = new ArrayList();
+ if (isPrimitive(this.datatype.getName())) {
+ list.add(configurationBean.getArticleNameUsedByService() + "_" + this.datatype.getName());
+ } else if (this.datatype.getName().equals("Object")) {
+ // dont do anything because object has no value
+ } else {
+ processDatatype(this.datatype, central, configurationBean.getArticleNameUsedByService(), list);
+ }
+ // add the input port called mobyData('datatypeName')
+ addInput("mobyData('" + this.datatype.getName() + "')", 0, true,
+ new ArrayList<Class<? extends ExternalReferenceSPI>>(),
+ String.class);
+ // add the namespace/id ports to the processor
+ addOutput("namespace", 1, "text/xml");
+ addOutput("id", 1, "text/xml");
+
+ // list contains the output ports i have to create
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ String portName = (String) it.next();
+ if (portName.equals(configurationBean.getArticleNameUsedByService()+"_id") || portName.equals(configurationBean.getArticleNameUsedByService()+"_ns"))
+ continue;
+ addOutput(portName, 1, "text/xml");
+ }
+ }
+
+ private boolean isPrimitive(String name) {
+ if (name.equals("Integer") || name.equals("String") || name.equals("Float")
+ || name.equals("DateTime") || name.equals("Boolean")
+ )
+ return true;
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void processDatatype(MobyDataType dt, Central central, String currentName, List list) throws ActivityConfigurationException {
+
+ if (dt.getParentName() == null || dt.getParentName().trim().equals("")) {
+ //TODO should we throw an error or just return ...
+ return;
+ }
+
+ if (!dt.getParentName().equals("Object")) {
+ flattenChildType(dt.getParentName(), central, currentName, list);
+ } else {
+ list.add(currentName + "_id");
+ list.add(currentName + "_ns");
+ }
+
+ MobyRelationship[] relations = dt.getChildren();
+ for (int i = 0; i < relations.length; i++) {
+ MobyRelationship relation = relations[i];
+ switch (relation.getRelationshipType()) {
+ case CentralImpl.iHAS: {
+ // check for object or primitives
+ if (isPrimitive(relation.getDataTypeName()) || relation.getDataTypeName().equals("Object")) {
+ // object has no value ... only primitives do
+ if (!relation.getDataTypeName().equals("Object"))
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName() + (currentName.equals("") ? "" : "'"));
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName() + (currentName.equals("") ? "" : "'")+"_id");
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName() + (currentName.equals("") ? "" : "'")+"_ns");
+ }
+ else {
+ flattenChildType(relation.getDataTypeName(), central, currentName
+ + (currentName.equals("") ? "" : "_'") + relation.getName() + (currentName.equals("") ? "" : "'"), list);
+ }
+ }
+ break;
+ case CentralImpl.iHASA: {
+ // check for object or primitives ...
+ if (isPrimitive(relation.getDataTypeName()) || relation.getDataTypeName().equals("Object")) {
+ // object has no value ... only primitives do
+ if (!relation.getDataTypeName().equals("Object"))
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName()+ (currentName.equals("") ? "" : "'"));
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName() + (currentName.equals("") ? "" : "'")+"_id");
+ list.add(currentName + (currentName.equals("") ? "" : "_'")
+ + relation.getName() + (currentName.equals("") ? "" : "'")+"_ns");
+ }
+ else {
+
+ flattenChildType(relation.getDataTypeName(), central, currentName
+ + (currentName.equals("") ? "" : "_'") + relation.getName() + (currentName.equals("") ? "" : "'"), list);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private void flattenChildType(String name, Central central, String current, List list) throws ActivityConfigurationException {
+ MobyDataType dt = null;
+ try {
+ dt = central.getDataType(name);
+ } catch (MobyException e) {
+ throw new ActivityConfigurationException(
+ "There was a problem getting information from the MobyCentral registry at "
+ + configurationBean.getRegistryEndpoint() + System.getProperty("line.separator")
+ + e.getLocalizedMessage());
+ } catch (NoSuccessException e) {
+ throw new ActivityConfigurationException(
+ "There was no success in getting information from the MobyCentral registry at "
+ + configurationBean.getRegistryEndpoint() + System.getProperty("line.separator")
+ + e.getLocalizedMessage());
+ }
+ processDatatype(dt, central, current, list);
+ }
+
+ private ArrayList<String> getNames(String names) {
+ ArrayList<String> list = new ArrayList<String>();
+ ArrayList<String> temp = new ArrayList<String>();
+ if (names == null || names.trim().length() == 0)
+ return list;
+ Scanner s = new Scanner(names).useDelimiter("_'");
+ while (s.hasNext()) {
+ temp.add(s.next());
+ }
+ s.close();
+
+ for (String str : temp) {
+ if (str.indexOf("'_") >= 0) {
+ String[] strings = str.split("'_");
+ for (int i = 0; i < strings.length; i++) {
+ list.add(strings[i].replaceAll("'", ""));
+ }
+ } else {
+ list.add(str.replaceAll("'", ""));
+ }
+ }
+
+ if (list.size() == 1) {
+ if (endsWithPrimitive(list.get(0))) {
+ String name = list.remove(0);
+ int i = name.lastIndexOf("_");
+ name = name.substring(0, i);
+ list.add(name);
+ }
+ } else if (isPrimitive(list.get(list.size()-1))) {
+ // remove the last entry if its a primitive ... legacy reasons
+ list.remove(list.size()-1);
+ }
+ return list;
+ }
+
+ private static boolean endsWithPrimitive(String name) {
+ if (name.endsWith("_Integer") || name.endsWith("_String") || name.endsWith("_Float")
+ || name.endsWith("_DateTime") || name.endsWith("_Boolean"))
+ return true;
+ return false;
+ }
+
+ protected void addOutput(String portName, int portDepth, String type) {
+ OutputPort port = edits.createActivityOutputPort(
+ portName, portDepth, portDepth);
+ MimeType mimeType = new MimeType();
+ mimeType.setText(type);
+ try {
+ edits.getAddAnnotationChainEdit(port, mimeType).doEdit();
+ } catch (EditException e) {
+ logger.debug("Error adding MimeType annotation to port", e);
+ }
+ outputPorts.add(port);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityConfigurationBean.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityConfigurationBean.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityConfigurationBean.java
new file mode 100644
index 0000000..1f02e7e
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityConfigurationBean.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+
+/**
+ * A configuration bean specific to the Moby Parse Datatype activity.
+ *
+ * @author David Withers
+ */
+@ConfigurationBean(uri = MobyParseDatatypeActivity.URI + "#Config")
+public class MobyParseDatatypeActivityConfigurationBean {
+
+ private String datatypeName="";
+
+ private String registryEndpoint="";
+
+ private String articleNameUsedByService="";
+
+ /**
+ * Returns the datatypeName.
+ *
+ * @return the datatypeName
+ */
+ public String getDatatypeName() {
+ return datatypeName;
+ }
+
+ /**
+ * Sets the datatypeName.
+ *
+ * @param datatypeName the new datatypeName
+ */
+ @ConfigurationProperty(name = "datatypeName", label = "Datatype Name", description = "")
+ public void setDatatypeName(String datatypeName) {
+ this.datatypeName = datatypeName;
+ }
+
+ /**
+ * Returns the registryEndpoint.
+ *
+ * @return the registryEndpoint
+ */
+ public String getRegistryEndpoint() {
+ return registryEndpoint;
+ }
+
+ /**
+ * Sets the registryEndpoint.
+ *
+ * @param registryEndpoint the new registryEndpoint
+ */
+ @ConfigurationProperty(name = "registryEndpoint", label = "Registry Endpoint", description = "")
+ public void setRegistryEndpoint(String registryEndpoint) {
+ this.registryEndpoint = registryEndpoint;
+ }
+
+ /**
+ * Returns the articleNameUsedByService.
+ *
+ * @return the articleNameUsedByService
+ */
+ public String getArticleNameUsedByService() {
+ return articleNameUsedByService;
+ }
+
+ /**
+ * Sets the articleNameUsedByService.
+ *
+ * @param articleNameUsedByService the new articleNameUsedByService
+ */
+ @ConfigurationProperty(name = "articleNameUsedByService", label = "Article Name Used By Service", description = "")
+ public void setArticleNameUsedByService(String articleNameUsedByService) {
+ this.articleNameUsedByService = articleNameUsedByService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityFactory.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityFactory.java
new file mode 100644
index 0000000..8da531e
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityFactory.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.biomoby;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory;
+
+/**
+ * An {@link ActivityFactory} for creating <code>MobyParseDatatypeActivity</code>.
+ *
+ * @author David Withers
+ */
+public class MobyParseDatatypeActivityFactory implements ActivityFactory {
+
+ @Override
+ public MobyParseDatatypeActivity createActivity() {
+ return new MobyParseDatatypeActivity();
+ }
+
+ @Override
+ public URI getActivityURI() {
+ return URI.create(MobyParseDatatypeActivity.URI);
+ }
+
+ @Override
+ public Object createActivityConfiguration() {
+ return new MobyParseDatatypeActivityConfigurationBean();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityHealthChecker.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityHealthChecker.java
new file mode 100644
index 0000000..0ca0d38
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/MobyParseDatatypeActivityHealthChecker.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * This file is a component of the Taverna project, and is licensed under the
+ * GNU LGPL. Copyright Edward Kawas, The BioMoby Project
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+
+import net.sf.taverna.t2.workflowmodel.health.RemoteHealthChecker;
+import net.sf.taverna.t2.workflowmodel.processor.activity.DisabledActivity;
+
+
+/**
+ * A health checker for the Moby Parse Datatype activity.
+ *
+ * @author David Withers
+ */
+public class MobyParseDatatypeActivityHealthChecker extends RemoteHealthChecker {
+
+
+ public boolean canVisit(Object subject) {
+ if (subject == null) {
+ return false;
+ }
+ if (subject instanceof MobyParseDatatypeActivity) {
+ return true;
+ }
+ if (subject instanceof DisabledActivity) {
+ return (((DisabledActivity) subject).getActivity() instanceof MobyParseDatatypeActivity);
+ }
+ return false;
+ }
+
+ public VisitReport visit(Object o, List<Object> ancestors) {
+ Activity activity = (Activity) o;
+ MobyParseDatatypeActivityConfigurationBean configuration = null;
+ if (activity instanceof MobyParseDatatypeActivity) {
+ configuration = (MobyParseDatatypeActivityConfigurationBean) activity.getConfiguration();
+ } else if (activity instanceof DisabledActivity) {
+ configuration = (MobyParseDatatypeActivityConfigurationBean) ((DisabledActivity) activity).getActivityConfiguration();
+ }
+ return contactEndpoint(activity, configuration.getRegistryEndpoint());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-bioinformatics/blob/709e8c1c/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ParseMobyXML.java
----------------------------------------------------------------------
diff --git a/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ParseMobyXML.java b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ParseMobyXML.java
new file mode 100644
index 0000000..042b6e8
--- /dev/null
+++ b/taverna-biomoby-activity/src/main/java/net/sf/taverna/t2/activities/biomoby/ParseMobyXML.java
@@ -0,0 +1,192 @@
+/*
+ * This file is a component of the Taverna project,
+ * and is licensed under the GNU LGPL.
+ * Copyright Edward Kawas, The BioMoby Project
+ */
+package net.sf.taverna.t2.activities.biomoby;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.biomoby.shared.MobyNamespace;
+import org.biomoby.shared.data.MobyContentInstance;
+import org.biomoby.shared.data.MobyDataBoolean;
+import org.biomoby.shared.data.MobyDataComposite;
+import org.biomoby.shared.data.MobyDataFloat;
+import org.biomoby.shared.data.MobyDataInstance;
+import org.biomoby.shared.data.MobyDataInt;
+import org.biomoby.shared.data.MobyDataJob;
+import org.biomoby.shared.data.MobyDataObject;
+import org.biomoby.shared.data.MobyDataObjectVector;
+import org.biomoby.shared.data.MobyDataString;
+import org.biomoby.shared.data.MobyDataUtils;
+import org.biomoby.registry.meta.Registry;
+
+/**
+ * This class is used to help parse BioMOBY messages.
+ *
+ * @author Edward Kawas
+ *
+ */
+public class ParseMobyXML {
+
+ private static Logger logger = Logger.getLogger(ParseMobyXML.class);
+
+ public static final int NAMESPACE = -10;
+
+ public static final int ID = -20;
+
+ public static final int VALUE = -30;
+
+ private static final List<Integer> allowables;
+
+ static {
+ allowables = new ArrayList<Integer>();
+ allowables.add(NAMESPACE);
+ allowables.add(ID);
+ allowables.add(VALUE);
+ }
+
+ /**
+ * PRECONDITION: XML is valid MOBY xml and contains exactly 1 invocation
+ * message containing our simple element
+ *
+ * @param names
+ * an array of article names in the order that we will
+ * extract our information
+ * @param type
+ * one of {NAMESPACE | ID | VALUE} denoting what exactly it
+ * is that you would like returned
+ * @param xml
+ * the MOBY xml containing the data to extract
+ * @param endpoint
+ * the BioMOBY registry endpoint to use
+ * @return a list of strings representing what it is you asked for
+ */
+ public static ArrayList<String> getContentForDataType(
+ ArrayList<String> names, int type, String xml, String endpoint) {
+ if (!allowables.contains(type) || names == null || names.size() == 0
+ || xml == null || xml.trim().length() == 0) {
+ // nothing to return
+ logger.warn("Parser invoked on an empty message ...");
+ return new ArrayList<String>();
+ }
+ MobyContentInstance contents;
+ try {
+ contents = MobyDataUtils.fromXMLDocument(new ByteArrayInputStream(
+ xml.getBytes("UTF8")), new Registry(endpoint, endpoint,
+ "http://domain.com/MOBY/Central"));
+ } catch (Exception e) {
+ logger.error("There was a problem parsing the input XML:\n" + xml
+ + "\n", e);
+ return new ArrayList<String>();
+ }
+ if (contents.keySet().size() != 1) {
+ return new ArrayList<String>();
+ }
+
+ ArrayList<String> clone = new ArrayList<String>();
+ clone.addAll(names);
+ ArrayList<String> output = new ArrayList<String>();
+ // should be exactly 1 job!
+ Iterator<String> jobIDs = contents.keySet().iterator();
+ while (jobIDs.hasNext()) {
+ MobyDataJob job = (MobyDataJob) contents.get(jobIDs.next());
+ // get the instance
+ MobyDataInstance data = job.get(clone.remove(0));
+ if (data == null)
+ return output;
+ recurse(clone, data, output, type);
+ }
+ return output;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void recurse(ArrayList<String> names, MobyDataInstance data,
+ ArrayList<String> output, int type) {
+ // base case => we have finally found the element of interest
+ if (names.isEmpty()) {
+ baseCase(data, output, type);
+ return;
+ }
+ if (data instanceof MobyDataObjectVector) {
+ // recurse on the children -- the recursion will extract by
+ // articlename
+ MobyDataObjectVector vector = (MobyDataObjectVector) data;
+ // recurse on the has relationship
+ for (Iterator i = vector.iterator(); i.hasNext();) {
+ recurse((ArrayList) (names.clone()), (MobyDataInstance) i
+ .next(), output, type);
+ }
+
+ } else if (data instanceof MobyDataComposite) {
+ // recurse on the child given by name.get(0)
+ MobyDataInstance d = ((MobyDataComposite) data).remove(names
+ .remove(0));
+ recurse((ArrayList) (names.clone()), d, output, type);
+ } else if (data instanceof MobyDataBoolean) {
+ baseCase(data, output, type);
+ } else if (data instanceof MobyDataFloat) {
+ baseCase(data, output, type);
+ } else if (data instanceof MobyDataInt) {
+ baseCase(data, output, type);
+ } else if (data instanceof MobyDataString) {
+ baseCase(data, output, type);
+ }
+
+ }
+
+ private static void baseCase(MobyDataInstance data,
+ ArrayList<String> output, int type) {
+ if (data == null)
+ return;
+ switch (type) {
+ case NAMESPACE: {
+ if (data instanceof MobyDataObjectVector) {
+ MobyDataObjectVector vector = (MobyDataObjectVector) data;
+ for (Iterator i = vector.iterator(); i.hasNext();) {
+ MobyNamespace[] namespaces = ((MobyDataObject) i.next())
+ .getNamespaces();
+ for (int j = 0; j < namespaces.length; j++) {
+ output.add(namespaces[j].getName());
+ }
+ }
+ } else {
+ MobyNamespace[] namespaces = ((MobyDataObject) data)
+ .getNamespaces();
+ for (int j = 0; j < namespaces.length; j++) {
+ output.add(namespaces[j].getName());
+ }
+ }
+ }
+ break;
+ case ID: {
+ if (data instanceof MobyDataObjectVector) {
+ MobyDataObjectVector vector = (MobyDataObjectVector) data;
+ for (Iterator i = vector.iterator(); i.hasNext();) {
+ output.add(((MobyDataObject) i.next()).getId());
+ }
+ } else {
+ output.add(((MobyDataObject) data).getId());
+ }
+ }
+ break;
+ case VALUE: {
+ if (data instanceof MobyDataObjectVector) {
+ MobyDataObjectVector vector = (MobyDataObjectVector) data;
+ for (Iterator i = vector.iterator(); i.hasNext();) {
+ output.add(((MobyDataObject) i.next()).getValue());
+ }
+ } else {
+ output.add(((MobyDataObject) data).getValue());
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}