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/03/20 15:22:26 UTC

[12/51] [abbrv] [partial] incubator-taverna-workbench git commit: taverna-workbench-* -> taverna-*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/BioCatalogueWSDLActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/BioCatalogueWSDLActivityHealthChecker.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/BioCatalogueWSDLActivityHealthChecker.java
new file mode 100644
index 0000000..c30ec8f
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/BioCatalogueWSDLActivityHealthChecker.java
@@ -0,0 +1,199 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.log4j.Logger;
+import org.biocatalogue.x2009.xml.rest.MonitoringStatusLabel;
+import org.biocatalogue.x2009.xml.rest.Service;
+import org.biocatalogue.x2009.xml.rest.ServiceTest;
+import org.biocatalogue.x2009.xml.rest.TestScript;
+
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.biocatalogue.model.Util;
+import net.sf.taverna.biocatalogue.model.connectivity.BioCatalogueClient;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivityConfigurationBean;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentFactory;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+
+
+/**
+ * A {@link HealthChecker} for a {@link WSDLActivity}.
+ *
+ * @author Sergejs Aleksejevs
+ */
+public class BioCatalogueWSDLActivityHealthChecker implements HealthChecker<WSDLActivity>
+{
+  private static final int MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA = 48 * 60 * 60 * 1000;  // 48hrs
+  
+  
+  private Logger logger;
+  
+  public BioCatalogueWSDLActivityHealthChecker() {
+    logger = Logger.getLogger(BioCatalogueWSDLActivityHealthChecker.class);
+  }
+  
+  
+  public boolean canVisit(Object subject) {
+    return (subject instanceof WSDLActivity);
+  }
+  
+  
+  public VisitReport visit(WSDLActivity activity, List<Object> ancestors)
+  {
+    WSDLActivityConfigurationBean configBean = activity.getConfiguration();
+    SoapOperationIdentity soapOpIdentity = new SoapOperationIdentity(configBean.getWsdl(), configBean.getOperation(), null);
+    
+    try {
+      // make BioCatalogue API request to fetch the data
+      Service serviceWithMonitoringData = BioCatalogueClient.getInstance().lookupParentServiceMonitoringData(soapOpIdentity);
+      MonitoringStatusLabel.Enum serviceStatusLabel = null;
+      
+      
+      VisitReport.Status status = null;
+      String visitReportLabel = null;
+      String visitReportExplanation = null;
+      List<VisitReport> subReports = new ArrayList<VisitReport>();
+      
+      
+      if (serviceWithMonitoringData == null) {
+        // BioCatalogue doesn't "know" about this service - it appears not to be registered;
+        // --> nothing to report to Taverna
+        return (null);
+      }
+      else if (serviceWithMonitoringData.getLatestMonitoringStatus() == null) {
+        // BioCatalogue "knows" this service, but for some reason there was no monitoring data available;
+        // possibly an API change? either way --> nothing to report to Taverna
+        return (null);
+      }
+      else
+      {
+        Calendar lastCheckedAt = serviceWithMonitoringData.getLatestMonitoringStatus().getLastChecked();
+        String agoString = Util.getAgoString(lastCheckedAt, Calendar.getInstance(), MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA);
+        if (agoString == null) {
+          return (null);
+        }
+        
+        serviceStatusLabel = serviceWithMonitoringData.getLatestMonitoringStatus().getLabel();
+        switch (serviceStatusLabel.intValue()) {
+          case MonitoringStatusLabel.INT_PASSED:
+            visitReportLabel = "Service Catalogue: all tests passed " + agoString;
+            visitReportExplanation = "The Service Catalogue reports that all available tests for this WSDL service have " +
+            		                     "been successful. They have been last executed " + agoString;
+            status = Status.OK;
+            break;
+                  
+          case MonitoringStatusLabel.INT_WARNING:
+          case MonitoringStatusLabel.INT_FAILED:
+            visitReportLabel = "Service Catalogue: some tests failed " + agoString;
+            visitReportExplanation = "Some test scripts for this WSDL service have failed";
+            
+            // only extract data about failing test scripts
+            subReports = createTestScriptSubReportsForFailingService(activity, serviceWithMonitoringData);
+            if (subReports.size() == 0) {
+              // failing tests must have been for endpoint / WSDL location - but not for scripts;
+              // Taverna doesn't need to know about the former, as it replicates internal checks
+              return (null);
+            }
+            else {
+              // determine the worst status and report as the one of the collection of subreports
+              status = VisitReport.getWorstStatus(subReports);
+            }
+            break;
+          
+          case MonitoringStatusLabel.INT_UNCHECKED:
+            // monitoring record states that the status of this service was not (yet) checked;
+            // possibly monitoring on BioCatalogue was switched off before this service was registered;
+            // --> nothing to report to Taverna
+            return (null);
+                  
+          default:
+            visitReportLabel = "Service Catalogue: unknown monitoring status received - \"" + serviceStatusLabel.toString() + "\"";
+            visitReportExplanation = "The Service Catalogue has returned a new monitoring status for this service: \"" +
+                                     serviceStatusLabel.toString() + "\"\n\n" +
+                                     "It has never been used before and probably indicates a change in the Service Catalogue API. " +
+                                     "Please report this issue to the Service Catalogue developers.";
+            status = Status.WARNING;
+            break;
+        }
+      }
+      
+      // wrap determined values into a single VisitReport object; then attach data to identify
+      // this service in associated VisitExplainer
+      VisitReport report = new VisitReport(BioCatalogueWSDLActivityHealthCheck.getInstance(), activity, 
+                                           visitReportLabel, BioCatalogueWSDLActivityHealthCheck.MESSAGE_IN_VISIT_REPORT, status, subReports);
+      report.setProperty(BioCatalogueWSDLActivityHealthCheck.WSDL_LOCATION_PROPERTY, soapOpIdentity.getWsdlLocation());
+      report.setProperty(BioCatalogueWSDLActivityHealthCheck.OPERATION_NAME_PROPERTY, soapOpIdentity.getOperationName());
+      report.setProperty(BioCatalogueWSDLActivityHealthCheck.EXPLANATION_MSG_PROPERTY, visitReportExplanation);
+      
+      return (report);
+    }
+    catch (Exception e) {
+      // not sure what could have happened - it will be visible in the logs
+      logger.error("Unexpected error while performing health check for " + 
+                   soapOpIdentity.getWsdlLocation() + " service.", e);
+      return (null);
+    }
+  }
+  
+  
+  private List<VisitReport> createTestScriptSubReportsForFailingService(WSDLActivity activity, Service serviceWithMonitoringData)
+  {
+    List<VisitReport> subReports = new ArrayList<VisitReport>();
+    
+    try {
+      List<ServiceTest> serviceTests = serviceWithMonitoringData.getMonitoring().getTests().getServiceTestList();
+      for (ServiceTest test : serviceTests)
+      {
+        if (test.getTestType().getTestScript() != null &&
+            test.getTestType().getTestScript()instanceof TestScript)
+        {
+          TestScript testScript = test.getTestType().getTestScript();
+          
+          String agoString = Util.getAgoString(test.getLatestStatus().getLastChecked(), Calendar.getInstance(), 
+                                               MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA);
+          
+          // only proceed if this test wasn't run too long ago
+          if (agoString != null) {
+            String label = "Service Catalogue: \"" + testScript.getName() + "\" test script " + test.getLatestStatus().getLabel();
+            VisitReport report = new VisitReport(BioCatalogueWSDLActivityHealthCheck.getInstance(), activity, 
+                label, BioCatalogueWSDLActivityHealthCheck.MESSAGE_IN_VISIT_REPORT,
+                ServiceMonitoringStatusInterpreter.translateBioCatalogueStatusForTaverna(test.getLatestStatus().getLabel()));
+            report.setProperty(BioCatalogueWSDLActivityHealthCheck.WSDL_LOCATION_PROPERTY, activity.getConfiguration().getWsdl());
+            report.setProperty(BioCatalogueWSDLActivityHealthCheck.OPERATION_NAME_PROPERTY, activity.getConfiguration().getOperation());
+            report.setProperty(BioCatalogueWSDLActivityHealthCheck.EXPLANATION_MSG_PROPERTY,
+                               "This test was last executed " + agoString + "." +
+                               "\n\n" + StringEscapeUtils.escapeHtml(test.getLatestStatus().getMessage()) +
+                               "\n\n---- Test script description ----\n" + StringEscapeUtils.escapeHtml(testScript.getDescription()));
+            
+            subReports.add(report);
+          }
+        }
+      }
+    }
+    catch (Exception e) {
+      // log the error, but do not terminate the method - maybe some sub reports were successfully
+      // generated, in which case at least partial result can be returned
+      logger.error("Encountered unexpected problem while trying to generate a collection of sub-reports " +
+      		         "for a failing service: " + activity.getConfiguration().getWsdl(), e);
+    }
+    
+    return (subReports);
+  }
+  
+  
+  /**
+   * Health check for the WSDL activities involves fetching
+   * the monitoring status of each activity from BioCatalogue - 
+   * this *may* be time consuming.
+   */
+  public boolean isTimeConsuming() {
+    return true;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceHealthChecker.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceHealthChecker.java
new file mode 100644
index 0000000..8e85e61
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceHealthChecker.java
@@ -0,0 +1,280 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.log4j.Logger;
+import org.biocatalogue.x2009.xml.rest.ResourceLink;
+import org.biocatalogue.x2009.xml.rest.RestMethod;
+import org.biocatalogue.x2009.xml.rest.Service;
+import org.biocatalogue.x2009.xml.rest.ServiceTest;
+import org.biocatalogue.x2009.xml.rest.SoapOperation;
+
+import net.sf.taverna.biocatalogue.model.BioCataloguePluginConstants;
+import net.sf.taverna.biocatalogue.model.Resource;
+import net.sf.taverna.biocatalogue.model.Resource.TYPE;
+import net.sf.taverna.biocatalogue.model.ResourceManager;
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.biocatalogue.model.SoapProcessorIdentity;
+import net.sf.taverna.biocatalogue.model.connectivity.BioCatalogueClient;
+import net.sf.taverna.biocatalogue.ui.JClickableLabel;
+import net.sf.taverna.biocatalogue.ui.JWaitDialog;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponent;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentFactory;
+
+
+/**
+ * This class helps with "health checks" of individual Taverna processors
+ * (i.e. SOAP operations) and the workflows in general (by iterating through
+ * the processors).
+ * 
+ * @author Sergejs Aleksejevs
+ */
+public class ServiceHealthChecker
+{
+    private static Logger logger = Logger.getLogger(ServiceHealthChecker.class);
+
+    // deny creation of instances of this class
+  private ServiceHealthChecker() { };
+  
+  
+  // =====================================================================================================
+  //                      *** Health Check of Individual Service / Processor ***
+  // =====================================================================================================
+  
+  /**
+   * @param serviceURL URL of SOAP service or REST service on BioCatalogue;
+   *                   URL should be of the 
+   */
+  public static void checkServiceByURL(String serviceURL)
+  {
+    if (serviceURL != null) {
+      checkMonitoringStatusRoutine(serviceURL);
+    }
+    else {
+      // for some reason the URL of the service wasn't provided...
+      JOptionPane.showMessageDialog(null, "Cannot provide monitoring status for this service - " +
+      		                          "unknown service URL", "Service Catalogue Error", JOptionPane.ERROR_MESSAGE);
+    }
+  }
+  
+  
+  /**
+   * @param  
+   */
+  public static void checkResource(ResourceLink serviceOrOperationOrMethod)
+  {
+    if (serviceOrOperationOrMethod != null) {
+      checkMonitoringStatusRoutine(serviceOrOperationOrMethod);
+    }
+    else {
+      // for some reason resource object wasn't provided...
+      JOptionPane.showMessageDialog(null, "Cannot provide monitoring status - " +
+                                    "null reference received", "Service Catalogue Error", JOptionPane.ERROR_MESSAGE);
+    }
+  }
+  
+  
+  /**
+   * Used when invoked from the workflow diagram - e.g. when a URL of the specific
+   * resource on BioCatalogue is not known, but have enough of identifying data
+   * to proceed with health check.
+   * 
+   * @param soapOperationDetails
+   */
+  public static void checkWSDLProcessor(SoapOperationIdentity soapOperationDetails)
+  {
+    if (!soapOperationDetails.hasError()) {
+      checkMonitoringStatusRoutine(soapOperationDetails);
+    }
+    else {
+      // this error message comes from Integration class extracting SOAP operation details from the contextual selection
+      JOptionPane.showMessageDialog(null, soapOperationDetails.getErrorDetails(), "Service Catalogue Error", JOptionPane.WARNING_MESSAGE);
+    }
+  }
+  
+  
+  /**
+   * @param serviceOrSoapOperationToCheck Instance of SoapOperationIdentity representing Taverna processor
+   *                                      or String representing a URL of the service to check health for.
+   */
+  private static void checkMonitoringStatusRoutine(final Object serviceOrSoapOperationToCheck)
+  {
+    // helper variable to determine the kind of check to perform - the difference is minimal:
+    // wording in the status messages ("Web Service" | "processor" | "REST Service") and which method to call on
+    // the BioCatalogue client to fetch monitoring data
+    final boolean bCheckingService = (serviceOrSoapOperationToCheck instanceof String);
+    final boolean bCheckingWSDLProcessor = (serviceOrSoapOperationToCheck instanceof SoapOperationIdentity);
+    final boolean bCheckingResource = (serviceOrSoapOperationToCheck instanceof ResourceLink);
+    
+    final StringBuilder itemToCheck = new StringBuilder();
+    if (bCheckingService) {
+      itemToCheck.append("service");
+    }
+    else if (bCheckingWSDLProcessor) {
+      itemToCheck.append("WSDL service"); 
+    }
+    else if (bCheckingResource) {
+      TYPE resourceType = Resource.getResourceTypeFromResourceURL(((ResourceLink)serviceOrSoapOperationToCheck).getHref());
+      itemToCheck.append(resourceType.getTypeName());
+    }
+    
+    // create the wait dialog, but don't make it visible - first need to start the background processing thread
+    final JWaitDialog jwd = new JWaitDialog(MainComponent.dummyOwnerJFrame, "Checking "+itemToCheck+" status",
+    "Please wait while status of selected "+itemToCheck+" is being checked...");
+
+    new Thread(itemToCheck + " lookup and health check operation") {
+      public void run() {
+        try
+        {
+          BioCatalogueClient client = BioCatalogueClient.getInstance();
+          Service serviceMonitoringData = null;
+          
+          // attempt to get monitoring data from BioCatalogue - for this need to identify what type of
+          // item was provided as a parameter
+          if (bCheckingService) {
+            serviceMonitoringData = client.getBioCatalogueServiceMonitoringData((String)serviceOrSoapOperationToCheck);
+          }
+          else if (bCheckingWSDLProcessor) {
+            serviceMonitoringData = client.lookupParentServiceMonitoringData((SoapOperationIdentity)serviceOrSoapOperationToCheck); 
+          }
+          else if (bCheckingResource) {
+            String resourceURL = ((ResourceLink)serviceOrSoapOperationToCheck).getHref();
+            TYPE resourceType = Resource.getResourceTypeFromResourceURL(resourceURL);
+            
+//            if (resourceType == TYPE.Service) {
+//              serviceMonitoringData = client.getBioCatalogueServiceMonitoringData(resourceURL);
+//            }
+//            else
+            	if (resourceType == TYPE.SOAPOperation) {
+              String parentServiceURL = ((SoapOperation)serviceOrSoapOperationToCheck).getAncestors().getService().getHref();
+              serviceMonitoringData = client.getBioCatalogueServiceMonitoringData(parentServiceURL);
+            }
+            else if (resourceType == TYPE.RESTMethod) {
+              String parentServiceURL = ((RestMethod)serviceOrSoapOperationToCheck).getAncestors().getService().getHref();
+              serviceMonitoringData = client.getBioCatalogueServiceMonitoringData(parentServiceURL);
+            }
+            else {
+              JOptionPane.showMessageDialog(jwd, "Unexpected resource type - can't execute health check for this",
+                  "Service Catalogue Error", JOptionPane.ERROR_MESSAGE);
+              	logger.error("Service Catalogue: Could not perform health check for" + resourceType);
+            }
+          }
+          
+          
+          // need to make this assignment to make the variable final - otherwise unavailable inside the new thread...
+          final Service serviceWithMonitoringData = serviceMonitoringData;
+          SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+              if (serviceWithMonitoringData == null) {
+                jwd.setTitle("Service Catalogue - Information");
+                jwd.waitFinished(new JLabel("There is no information about this "+itemToCheck+" in the Service Catalogue",
+                    UIManager.getIcon("OptionPane.informationIcon"), JLabel.CENTER));
+              }
+              else if (serviceWithMonitoringData.getLatestMonitoringStatus() == null) {
+                jwd.setTitle("Service Catalogue Warning");
+                jwd.waitFinished(new JLabel("This "+itemToCheck+" is known to the Service Catalogue, but no monitoring data was available.",
+                    UIManager.getIcon("OptionPane.warningIcon"), JLabel.CENTER));
+              }
+              else
+              {
+                // set the overall status message
+                String overallStatusLabel = "<html><b>Overall status:</b><br>" +
+                         serviceWithMonitoringData.getLatestMonitoringStatus().getMessage() + "<br>" +
+                         "(last checked";
+                if (serviceWithMonitoringData.getLatestMonitoringStatus().getLastChecked() == null) {
+                  overallStatusLabel += ": never";
+                }
+                else {
+                  overallStatusLabel += " at " + BioCatalogueClient.getShortDateFormatter().format(
+                      serviceWithMonitoringData.getLatestMonitoringStatus().getLastChecked().getTime());
+                }
+                overallStatusLabel += ")</html>";
+                JLabel jlOverallStatus = new JLabel(overallStatusLabel);
+                
+                // create panel for additional status messages (e.g. endpoint, wsdl location, etc)
+                JPanel jpStatusMessages = new JPanel();
+                jpStatusMessages.setLayout(new BoxLayout(jpStatusMessages, BoxLayout.Y_AXIS));
+                
+                for (ServiceTest test : serviceWithMonitoringData.getMonitoring().getTests().getServiceTestList())
+                {
+                  // First get the service type
+                  String testLabel = "<html><br><b>";
+                  if (test.getTestType().getUrlMonitor() != null)
+                  {
+                    if (test.getTestType().getUrlMonitor().getUrl().endsWith("wsdl")) {
+                      // WSDL location test
+                      testLabel += "WSDL Location Availability:</b><br>" +
+                                   "URL: " + test.getTestType().getUrlMonitor().getUrl();
+                    }
+                    else {
+                      // Endpoint availability test
+                      testLabel += "Endpoint Availability:</b><br>" +
+                                   "URL: " + test.getTestType().getUrlMonitor().getUrl();
+                    }
+                  }
+                  else if (test.getTestType().getTestScript() != null) {
+                    // test script
+                    testLabel += "Test Script: " + test.getTestType().getTestScript().getName() + "</b>";
+                  }
+                  else {
+                    testLabel += "Unknown test type</b>";
+                  }
+                  testLabel += "<br>";
+                  
+                  // Add service results
+                  testLabel += test.getLatestStatus().getMessage() + "</html>";
+                  
+                  // Add the current test into the test messages panel
+                  jpStatusMessages.add(new JLabel(testLabel));
+                }
+                
+                // either way add the overall status on top of everything
+                jpStatusMessages.add(jlOverallStatus, 0);
+                jpStatusMessages.setBorder(new EmptyBorder(10,10,10,10));
+                JScrollPane jspStatusMessages = new JScrollPane(jpStatusMessages);
+                jspStatusMessages.setBorder(BorderFactory.createEmptyBorder());
+                
+                // *** Put everything together ***
+                JPanel jpHealthCheckStatus = new JPanel(new BorderLayout(15, 10));
+                jpHealthCheckStatus.add(new JLabel(ServiceMonitoringStatusInterpreter.getStatusIcon(serviceWithMonitoringData, false)),
+                             BorderLayout.WEST);
+                jpHealthCheckStatus.add(jspStatusMessages, BorderLayout.CENTER);
+                
+                jwd.setTitle("Service Catalogue - Monitoring Status");
+                jwd.waitFinished(jpHealthCheckStatus);
+              }
+            }
+          });
+        }
+        catch (Exception e) {
+          logger.error("Service Catalogue: Error occurred while checking status of selected", e);
+          jwd.setTitle("Service Catalogue - Error");
+          jwd.waitFinished(new JLabel("<html>An unexpected error occurred while checking status of selected " +
+                                      itemToCheck + "<br>Please see error log for details...",
+                                      UIManager.getIcon("OptionPane.errorIcon"), JLabel.CENTER));
+        }
+      }
+    }.start();
+    
+    jwd.setVisible(true);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceMonitoringStatusInterpreter.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceMonitoringStatusInterpreter.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceMonitoringStatusInterpreter.java
new file mode 100644
index 0000000..0742cef
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/health_check/ServiceMonitoringStatusInterpreter.java
@@ -0,0 +1,77 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check;
+
+import java.net.URL;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import net.sf.taverna.biocatalogue.model.ResourceManager;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+
+import org.biocatalogue.x2009.xml.rest.MonitoringStatus;
+import org.biocatalogue.x2009.xml.rest.MonitoringStatusLabel;
+import org.biocatalogue.x2009.xml.rest.Service;
+
+/**
+ * @author Sergejs Aleksejevs
+ */
+public class ServiceMonitoringStatusInterpreter
+{
+  // prevent instantiation of this class
+  private ServiceMonitoringStatusInterpreter() { /* do nothing */ }
+  
+  
+  /**
+   * @param serviceWithMonitoringData
+   * @param listingIconRequired True to get a small icon suitable for a JList entry;
+   *                            false to get a larger icon.
+   * @return
+   */
+  public static ImageIcon getStatusIcon(Service serviceWithMonitoringData, boolean listingIconRequired)
+  {
+    MonitoringStatus latestMonitoringStatus = serviceWithMonitoringData.getLatestMonitoringStatus();
+    if (latestMonitoringStatus == null) {
+    	return ResourceManager.getImageIcon((listingIconRequired ?
+                ResourceManager.SERVICE_STATUS_UNCHECKED_ICON :
+                    ResourceManager.SERVICE_STATUS_UNCHECKED_ICON_LARGE));
+    }
+	MonitoringStatusLabel.Enum serviceStatusLabel = latestMonitoringStatus.getLabel();
+    
+    switch (serviceStatusLabel.intValue()) {
+      case MonitoringStatusLabel.INT_PASSED:
+              return ResourceManager.getImageIcon((listingIconRequired ?
+                                                          ResourceManager.SERVICE_STATUS_PASSED_ICON :
+                                                          ResourceManager.SERVICE_STATUS_PASSED_ICON_LARGE));
+      case MonitoringStatusLabel.INT_WARNING:
+              return ResourceManager.getImageIcon((listingIconRequired ?
+                                                          ResourceManager.SERVICE_STATUS_WARNING_ICON :
+                                                          ResourceManager.SERVICE_STATUS_WARNING_ICON_LARGE));
+      case MonitoringStatusLabel.INT_FAILED:
+              return ResourceManager.getImageIcon((listingIconRequired ?
+                                                          ResourceManager.SERVICE_STATUS_FAILED_ICON :
+                                                          ResourceManager.SERVICE_STATUS_FAILED_ICON_LARGE));
+      case MonitoringStatusLabel.INT_UNCHECKED:
+              return ResourceManager.getImageIcon((listingIconRequired ?
+                                                          ResourceManager.SERVICE_STATUS_UNCHECKED_ICON :
+                                                          ResourceManager.SERVICE_STATUS_UNCHECKED_ICON_LARGE));
+      default:
+              return (ResourceManager.getImageIcon(ResourceManager.SERVICE_STATUS_UNKNOWN_ICON));
+    }
+    
+  }
+  
+  
+  public static VisitReport.Status translateBioCatalogueStatusForTaverna(MonitoringStatusLabel.Enum monitoringStatusLabelEnum)
+  {
+    switch (monitoringStatusLabelEnum.intValue()) {
+      case MonitoringStatusLabel.INT_PASSED:    return Status.OK;
+      case MonitoringStatusLabel.INT_WARNING:   return Status.WARNING;
+      case MonitoringStatusLabel.INT_FAILED:    return Status.SEVERE;
+      case MonitoringStatusLabel.INT_UNCHECKED: return Status.OK;      // not really OK, but Taverna isn't interested in missing data anyway 
+      default:                                  return Status.WARNING; // could be worth to pop up a warning in this case, as it may mean something has changed
+    }
+  }
+  
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/BioCatalogueContextualMenuSection.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/BioCatalogueContextualMenuSection.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/BioCatalogueContextualMenuSection.java
new file mode 100644
index 0000000..a5fb7a8
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/BioCatalogueContextualMenuSection.java
@@ -0,0 +1,62 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.menus;
+
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.biocatalogue.model.ResourceManager;
+import net.sf.taverna.t2.lang.ui.ShadedLabel;
+import net.sf.taverna.t2.ui.menu.AbstractMenuSection;
+import net.sf.taverna.t2.ui.menu.ContextualMenuComponent;
+import net.sf.taverna.t2.ui.menu.ContextualSelection;
+import net.sf.taverna.t2.ui.menu.DefaultContextualMenu;
+import net.sf.taverna.t2.workflowmodel.Dataflow;
+import net.sf.taverna.t2.workflowmodel.InputPort;
+import net.sf.taverna.t2.workflowmodel.Processor;
+
+
+public class BioCatalogueContextualMenuSection extends AbstractMenuSection implements ContextualMenuComponent
+{
+  // TODO - this shouldn't be here, must reference this field in AbstractMenuSection!!
+  public static final String SECTION_COLOR = "sectionColor";
+
+  
+  public static final URI BIOCATALOGUE_MENU_SECTION_ID = URI.create("http://biocatalogue.org/2010/contextMenu/biocatalogue_section");
+  private static final String SECTION_TITLE = "Service Catalogue";
+  
+  private ContextualSelection contextualSelection;
+  
+  
+  public BioCatalogueContextualMenuSection() {
+          super(DefaultContextualMenu.DEFAULT_CONTEXT_MENU, 100000, BIOCATALOGUE_MENU_SECTION_ID);
+  }
+
+  public ContextualSelection getContextualSelection() {
+          return contextualSelection;
+  }
+  
+  public void setContextualSelection(ContextualSelection contextualSelection) {
+    this.contextualSelection = contextualSelection;
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return super.isEnabled()
+                    && (getContextualSelection().getSelection() instanceof Dataflow ||
+                        getContextualSelection().getSelection() instanceof Processor ||
+                        getContextualSelection().getSelection() instanceof InputPort);
+  }
+  
+  @SuppressWarnings("serial")
+  protected Action createAction()
+  {
+    Action action = new AbstractAction(SECTION_TITLE, ResourceManager.getImageIcon(ResourceManager.FAVICON)) {
+      public void actionPerformed(ActionEvent e) {
+      }
+    };
+    action.putValue(SECTION_COLOR, ShadedLabel.GREEN);
+    return (action);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionInputPort.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionInputPort.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionInputPort.java
new file mode 100644
index 0000000..f94b0e6
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionInputPort.java
@@ -0,0 +1,43 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.menus;
+
+import java.awt.event.ActionEvent;
+import java.net.URISyntaxException;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JOptionPane;
+
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+
+import net.sf.taverna.t2.workflowmodel.InputPort;
+
+
+/**
+ * This class currently won't be used, as an entry for it was removed from
+ * META-INF/services/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
+ * 
+ * This is because no useful action is yet available for input/output ports.
+ * 
+ * @author Sergejs Aleksejevs
+ */
+public class MenuActionInputPort extends AbstractContextualMenuAction {
+
+	public MenuActionInputPort() throws URISyntaxException {
+		super(BioCatalogueContextualMenuSection.BIOCATALOGUE_MENU_SECTION_ID, 15);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new AbstractAction("InputPort") {
+			public void actionPerformed(ActionEvent e) {
+				JOptionPane.showMessageDialog(getContextualSelection().getRelativeToComponent(), "Hoho!");
+			}
+		};
+	}
+
+	@Override
+	public boolean isEnabled() {
+	  return (super.isEnabled() && getContextualSelection().getSelection() instanceof InputPort);
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionProcessorHealthCheck.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionProcessorHealthCheck.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionProcessorHealthCheck.java
new file mode 100644
index 0000000..c66d72b
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/menus/MenuActionProcessorHealthCheck.java
@@ -0,0 +1,51 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.menus;
+
+import java.awt.event.ActionEvent;
+import java.net.URISyntaxException;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.Integration;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check.ServiceHealthChecker;
+import net.sf.taverna.t2.workflowmodel.Processor;
+
+
+public class MenuActionProcessorHealthCheck extends AbstractContextualMenuAction {
+
+  public MenuActionProcessorHealthCheck() throws URISyntaxException {
+    super(BioCatalogueContextualMenuSection.BIOCATALOGUE_MENU_SECTION_ID, 20);
+  }
+
+  @SuppressWarnings("serial")
+@Override
+  protected Action createAction()
+  {
+    Action action = new AbstractAction("Service Health Check") {
+      public void actionPerformed(ActionEvent e) {
+        SoapOperationIdentity soapOperationDetails = Integration.extractSoapOperationDetailsFromProcessorContextualSelection(getContextualSelection());
+        ServiceHealthChecker.checkWSDLProcessor(soapOperationDetails);
+      }
+    };
+    action.putValue(Action.SHORT_DESCRIPTION, "Check monitoring status of this service");
+    return (action);
+  }
+
+  @Override
+  public boolean isEnabled()
+  {
+    // FIXME - this will only work for SOAP processors for now..
+    boolean isEnabled = super.isEnabled() && getContextualSelection().getSelection() instanceof Processor;
+    
+    if (isEnabled) {
+      SoapOperationIdentity soapOperationDetails = Integration.extractSoapOperationDetailsFromProcessorContextualSelection(getContextualSelection());
+      isEnabled = !soapOperationDetails.hasError();
+    }
+    
+    return isEnabled;
+  }
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueRESTServiceProvider.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueRESTServiceProvider.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueRESTServiceProvider.java
new file mode 100644
index 0000000..3c39b1d
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueRESTServiceProvider.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (C) 2008-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.ui.perspectives.biocatalogue.integration.service_panel;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.Icon;
+
+import org.apache.log4j.Logger;
+
+//import net.sf.taverna.t2.activities.rest.ui.servicedescription.RESTActivityIcon;
+import net.sf.taverna.t2.servicedescriptions.AbstractConfigurableServiceProvider;
+import net.sf.taverna.t2.servicedescriptions.impl.ServiceDescriptionRegistryImpl;
+
+/**
+ * Service provider for REST service added to the Service Panel through the
+ * BioCatalogue perspective.
+ * 
+ * @author Alex Nenadic
+ */
+public class BioCatalogueRESTServiceProvider extends
+	AbstractConfigurableServiceProvider<RESTFromBioCatalogueServiceDescription> {
+
+	public static final String PROVIDER_NAME = "Service Catalogue - selected services";
+	  
+	private static final URI providerId = URI
+	.create("http://taverna.sf.net/2010/service-provider/servicecatalogue/rest");
+	
+	private static Logger logger = Logger.getLogger(BioCatalogueRESTServiceProvider.class);
+
+	public BioCatalogueRESTServiceProvider(
+			RESTFromBioCatalogueServiceDescription restServiceDescription) {
+		super(restServiceDescription);
+	}
+	
+	public BioCatalogueRESTServiceProvider() {
+		super(new RESTFromBioCatalogueServiceDescription());
+	}
+	
+	@Override
+	protected List<? extends Object> getIdentifyingData() {
+		return getConfiguration().getIdentifyingData();
+	}
+
+	@Override
+	public void findServiceDescriptionsAsync(
+			FindServiceDescriptionsCallBack callBack) {
+	    callBack.status("Starting Service Catalogue REST Service Provider");
+		registerNewRESTMethod(getConfiguration(), callBack);
+	}
+
+	@Override
+	public Icon getIcon() {
+//		return RESTActivityIcon.getRESTActivityIcon();
+		return getConfiguration().getIcon();
+	}
+
+	@Override
+	public String getId() {
+		return providerId.toString();
+	}
+
+	@Override
+	public String getName() {
+		return "Service Catalogue REST";
+	}
+	
+	@Override
+	public String toString() {
+		return "Service Catalogue REST service " + getConfiguration().getName();
+	}
+	
+	public static boolean registerNewRESTMethod(
+			RESTFromBioCatalogueServiceDescription restServiceDescription,
+			FindServiceDescriptionsCallBack callBack)	{
+		if (callBack == null) {
+			// We are not adding service through a callback and
+			// findServiceDescriptionsAsync() -
+			// we are adding directly from the BioCatalogue perspective.
+			ServiceDescriptionRegistryImpl serviceDescriptionRegistry = ServiceDescriptionRegistryImpl
+					.getInstance();
+			serviceDescriptionRegistry
+					.addServiceDescriptionProvider(new BioCatalogueRESTServiceProvider(
+							restServiceDescription));
+			return true;
+		} else {
+			{
+				// Add the REST method to the Service Panel through the callback
+				callBack.partialResults(Collections
+						.singletonList(restServiceDescription));
+				callBack.finished();
+				return (true);
+			}
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueServiceProvider.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueServiceProvider.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueServiceProvider.java
new file mode 100644
index 0000000..87518c3
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueServiceProvider.java
@@ -0,0 +1,274 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.service_panel;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.Icon;
+import javax.wsdl.Operation;
+import javax.wsdl.WSDLException;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.biocatalogue.model.Util;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivityHealthChecker;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.BioCataloguePerspective;
+import net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.config.BioCataloguePluginConfiguration;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.parser.WSDLParser;
+
+public class BioCatalogueServiceProvider implements ServiceDescriptionProvider
+{
+  public static final String PROVIDER_NAME = "Service Catalogue - selected services";
+  
+  private static BioCatalogueServiceProvider instanceOfSelf = null;
+  private static FindServiceDescriptionsCallBack callBack;
+  
+  private static List<SoapOperationIdentity> registeredSOAPOperations;
+  private static List<RESTFromBioCatalogueServiceDescription> registeredRESTMethods;
+  
+  private static Logger logger = Logger.getLogger(BioCatalogueServiceProvider.class);
+  
+  
+	public BioCatalogueServiceProvider() {
+	  BioCatalogueServiceProvider.instanceOfSelf = this;
+	}
+	
+	@SuppressWarnings("unchecked")
+  public void findServiceDescriptionsAsync(FindServiceDescriptionsCallBack callBack)
+	{
+		BioCatalogueServiceProvider.callBack = callBack;
+    callBack.status("Starting Service Catalogue Service Provider");
+		
+    // --- Initilise the service provider with stored services ---
+    
+    // read stored settings
+    // NB! it's crucial to set the custom classloader, otherwise XStream would fail,
+    //     as it would attempt to use the default one, which wouldn't know about the
+    //     plugin's classes
+    logger.info("Starting to deserialise the list of services stored in the configuration file");
+    XStream xstream = new XStream(new DomDriver());
+    xstream.setClassLoader(BioCataloguePerspective.class.getClassLoader());
+    
+    BioCataloguePluginConfiguration configuration = BioCataloguePluginConfiguration.getInstance();
+    
+    // *** load stored SOAP operations ***
+    String loadedSOAPServicesXMLString = configuration.getProperty(BioCataloguePluginConfiguration.SOAP_OPERATIONS_IN_SERVICE_PANEL);
+    
+    Object loadedSOAPServices = (loadedSOAPServicesXMLString == null ?
+                                 null :
+                                 xstream.fromXML(loadedSOAPServicesXMLString));
+    
+    registeredSOAPOperations = (loadedSOAPServices == null || !(loadedSOAPServices instanceof List<?>) ?
+                                new ArrayList<SoapOperationIdentity>() :
+                                (List<SoapOperationIdentity>)loadedSOAPServices
+                               );
+    logger.info("Deserialised " + registeredSOAPOperations.size() + Util.pluraliseNoun("SOAP operation", registeredSOAPOperations.size()));
+    
+    // prepare the correct format of data for initialisation
+    List<ServiceDescription> results = new ArrayList<ServiceDescription>();
+    for (SoapOperationIdentity opId : registeredSOAPOperations) {
+      results.add(new WSDLOperationFromBioCatalogueServiceDescription(opId));
+    }
+    
+    
+    // *** load stored REST methods ***
+    String loadedRESTMethodsXMLString = configuration.getProperty(BioCataloguePluginConfiguration.REST_METHODS_IN_SERVICE_PANEL);
+    
+    Object loadedRESTMethods = (loadedRESTMethodsXMLString == null ?
+                                null :
+                                xstream.fromXML(loadedRESTMethodsXMLString));
+    
+    registeredRESTMethods = (loadedRESTMethods == null || !(loadedRESTMethods instanceof List<?>) ?
+                             new ArrayList<RESTFromBioCatalogueServiceDescription>() :
+                             (List<RESTFromBioCatalogueServiceDescription>)loadedRESTMethods);
+    logger.info("Deserialised " + registeredRESTMethods.size() + Util.pluraliseNoun("REST method", registeredRESTMethods.size()));
+    
+    results.addAll(registeredRESTMethods);
+		
+    
+		// *** send the services to the Service Panel ***
+		callBack.partialResults(results);
+		
+		
+		// NB! This is to be called when it is known that no more items will be added - 
+		// it's never true for this provider, as items may be added on user request
+		// at any time!
+		//
+		// callBack.finished();
+	}
+	
+	public Icon getIcon() {
+		return null;
+	}
+	
+	public String getName(){
+	  // TODO - not sure where this is used
+		return "My dummy service";
+	}
+	
+	public String getId() {
+    return "http://www.taverna.org.uk/2010/services/servicecatalogue";
+  }
+	
+	
+	/**
+	 * Adds a new "processor" - i.e. a WSDL operation into the main Service Panel.
+	 * 
+	 * @param wsdlLocation URL of the WSDL location of the operation to add.
+	 * @param operationName Name of the operation within specified WSDL document.
+	 * @return True if the operation was added;
+	 *         false if the service provided was not yet initiliased (unlikely) or
+	 *         when supplied strings were empty/null.
+	 */
+	public static boolean registerNewWSDLOperation(SoapOperationIdentity soapOperationDetails)
+	{
+	  if (BioCatalogueServiceProvider.instanceOfSelf == null || soapOperationDetails == null ||
+	      soapOperationDetails.getWsdlLocation() == null || soapOperationDetails.getWsdlLocation().length() == 0 ||
+	      soapOperationDetails.getOperationName() == null || soapOperationDetails.getOperationName().length() == 0)
+	  {
+	    // the service provider hasn't been initialised yet
+	    // OR not all details available
+	    return (false);
+	  }
+	  else
+	  {
+	    // record the newly added operation in the internal list
+	    registeredSOAPOperations.add(soapOperationDetails);
+	    
+	    // add the provided operation to the Service Panel
+	    ServiceDescription service = new WSDLOperationFromBioCatalogueServiceDescription(soapOperationDetails);
+	    BioCatalogueServiceProvider.callBack.partialResults(Collections.singletonList(service));
+	    return (true);
+	  }
+	    
+	}
+	
+	/**
+	 * Adds a SOAP/WSDL service and all of its operations into the Taverna's Service Panel.
+	 */
+	public static boolean registerNewWSDLService(String wsdlURL)
+	{
+	  if (BioCatalogueServiceProvider.instanceOfSelf == null || wsdlURL == null)
+	  {
+	    // the service provider hasn't been initialised yet
+	    // OR not all details available
+	    return (false);
+	  }
+	  else
+	  {
+		  // Do the same thing as in the WSDL service provider
+			callBack.status("Service Catalogue service provider: Parsing wsdl: " + wsdlURL);
+			WSDLParser parser = null;
+			try {
+				parser = new WSDLParser(wsdlURL);
+				List<Operation> operations = parser.getOperations();
+				callBack.status("Found " + operations.size() + " WSDL operations of service "
+						+ wsdlURL);
+				List<WSDLOperationFromBioCatalogueServiceDescription> items = new ArrayList<WSDLOperationFromBioCatalogueServiceDescription>();
+				for (Operation operation : operations) {
+					WSDLOperationFromBioCatalogueServiceDescription item;
+					try {
+						String operationName = operation.getName();
+						String operationDesc = parser.getOperationDocumentation(operationName);
+						String use = parser.getUse(operationName);
+						String style = parser.getStyle();
+						if (!WSDLActivityHealthChecker.checkStyleAndUse(style, use)) {
+							logger.warn("Unsupported style and use combination " + style + "/" + use + " for operation " + operationName + " from " + wsdlURL);
+							continue;
+						}
+						item = new WSDLOperationFromBioCatalogueServiceDescription(wsdlURL, operationName, operationDesc);
+						items.add(item);
+						
+					    // Record the newly added operation in the internal list
+						SoapOperationIdentity soapOperationDetails = new SoapOperationIdentity(wsdlURL, operationName, operationDesc);
+					    registeredSOAPOperations.add(soapOperationDetails);
+					} catch (UnknownOperationException e) {
+						String message = "Encountered an unexpected operation name:"
+								+ operation.getName();
+						callBack.fail(message, e);
+					    return false;
+					}
+				}
+				callBack.partialResults(items);
+				callBack.finished();
+				return true;
+			} catch (ParserConfigurationException e) {
+				String message = "Error configuring the WSDL parser";
+				callBack.fail(message, e);
+			    return false;
+			} catch (WSDLException e) {
+				String message = "There was an error with the wsdl: " + wsdlURL;
+				callBack.fail(message, e);
+			    return false;
+			} catch (IOException e) {
+				String message = "There was an IO error parsing the wsdl: " + wsdlURL
+						+ " Possible reason: the wsdl location was incorrect.";
+				callBack.fail(message, e);
+			    return false;
+			} catch (SAXException e) {
+				String message = "There was an error with the XML in the wsdl: "
+						+ wsdlURL;
+				callBack.fail(message, e);
+			    return false;
+			} catch (IllegalArgumentException e) { // a problem with the wsdl url
+				String message = "There was an error with the wsdl: " + wsdlURL + " "
+						+ "Possible reason: the wsdl location was incorrect.";
+				callBack.fail(message, e);
+			    return false;
+			} catch (Exception e) { // anything else we did not expect
+				String message = "There was an error with the wsdl: " + wsdlURL;
+				callBack.fail(message, e);
+			    return false;
+			}
+		}
+	    
+	}
+	
+	
+	public static boolean registerNewRESTMethod(RESTFromBioCatalogueServiceDescription restServiceDescription)
+	{
+	  if (restServiceDescription == null) {
+	    return (false);
+	  }
+	  else
+	  {
+	    // record the newly added method in the internal list
+	    registeredRESTMethods.add(restServiceDescription);
+	    
+	    // add the provided method to the Service Panel
+	    BioCatalogueServiceProvider.callBack.partialResults(Collections.singletonList(restServiceDescription));
+	    return (true);
+	  }
+	}
+	
+	
+	public static List<SoapOperationIdentity> getRegisteredSOAPOperations() {
+	  return (registeredSOAPOperations);
+	}
+	
+	public static List<RESTFromBioCatalogueServiceDescription> getRegisteredRESTMethods() {
+    return (registeredRESTMethods);
+  }
+  
+	
+	/**
+	 * Clears internal lists of stored SOAP operations / REST methods.
+	 * Therefore, once Taverna is restarted, the stored services will
+	 * be effectively "forgotten".
+	 */
+	public static void clearRegisteredServices() {
+	  registeredRESTMethods.clear();
+	  registeredSOAPOperations.clear();
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueWSDLOperationServiceProvider.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueWSDLOperationServiceProvider.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueWSDLOperationServiceProvider.java
new file mode 100644
index 0000000..62a39d7
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/BioCatalogueWSDLOperationServiceProvider.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (C) 2008-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.ui.perspectives.biocatalogue.integration.service_panel;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.Icon;
+import javax.wsdl.Operation;
+import javax.wsdl.WSDLException;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.xml.sax.SAXException;
+
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivityHealthChecker;
+import net.sf.taverna.t2.servicedescriptions.AbstractConfigurableServiceProvider;
+import net.sf.taverna.t2.servicedescriptions.impl.ServiceDescriptionRegistryImpl;
+import net.sf.taverna.wsdl.parser.UnknownOperationException;
+import net.sf.taverna.wsdl.parser.WSDLParser;
+
+/**
+ * Service provider for WSDL operations added to the Service Panel through the
+ * BioCatalogue perspective.
+ * 
+ * @author Alex Nenadic
+ */
+public class BioCatalogueWSDLOperationServiceProvider extends
+	AbstractConfigurableServiceProvider<WSDLOperationFromBioCatalogueServiceDescription> {
+
+	public BioCatalogueWSDLOperationServiceProvider(
+			WSDLOperationFromBioCatalogueServiceDescription wsdlOperationDescription) {
+		super(wsdlOperationDescription);
+	}
+
+	public BioCatalogueWSDLOperationServiceProvider() {
+		super(new WSDLOperationFromBioCatalogueServiceDescription(new SoapOperationIdentity("", "", "")));
+	}
+	
+	public static final String PROVIDER_NAME = "Service Catalogue - selected services";
+	  
+	private static final URI providerId = URI
+	.create("http://taverna.sf.net/2010/service-provider/servicecatalogue/wsdl");
+	
+	private static Logger logger = Logger.getLogger(BioCatalogueWSDLOperationServiceProvider.class);
+
+	@Override
+	protected List<? extends Object> getIdentifyingData() {
+		return getConfiguration().getIdentifyingData();
+	}
+
+	@Override
+	public void findServiceDescriptionsAsync(
+			FindServiceDescriptionsCallBack callBack) {
+	    callBack.status("Starting Service Catalogue WSDL Service Provider");
+		registerWSDLOperation(getConfiguration(), callBack);
+	}
+
+	@Override
+	public Icon getIcon() {
+		return getConfiguration().getIcon();
+	}
+
+	@Override
+	public String getId() {
+		return providerId.toString();
+	}
+
+	@Override
+	public String getName() {
+		return "Service Catalogue WSDL";
+	}
+	
+	@Override
+	public String toString() {
+		return "Service Catalogue WSDL service " + getConfiguration().getName();
+	}
+	
+	public static boolean registerWSDLOperation(
+			WSDLOperationFromBioCatalogueServiceDescription wsdlOperationDescription,
+			FindServiceDescriptionsCallBack callBack)	{
+		
+		if (callBack == null) {
+			// We are not adding service through Taverna service registry's callback and
+			// findServiceDescriptionsAsync() -
+			// we are adding directly from the BioCatalogue perspective.
+			ServiceDescriptionRegistryImpl serviceDescriptionRegistry = ServiceDescriptionRegistryImpl
+					.getInstance();
+			serviceDescriptionRegistry
+					.addServiceDescriptionProvider(new BioCatalogueWSDLOperationServiceProvider(
+							wsdlOperationDescription));
+			return true;
+		} else {
+			// Add the WSDL operation to the Service Panel through the callback
+			callBack.partialResults(Collections
+					.singletonList(wsdlOperationDescription));
+			callBack.finished();
+			return (true);
+		}
+	}
+
+	/**
+	 * Adds a SOAP/WSDL service and all of its operations into the Taverna's Service Panel.
+	 */
+	public static boolean registerWSDLService(String wsdlURL, FindServiceDescriptionsCallBack callBack)
+	{
+		String errorMessage = null;
+		Exception ex = null;
+		
+		List<Operation> operations = null;
+		List<WSDLOperationFromBioCatalogueServiceDescription> items = null;
+		
+		// Do the same thing as in the WSDL service provider
+		WSDLParser parser = null;
+		try {
+			parser = new WSDLParser(wsdlURL);
+			operations = parser.getOperations();
+			items = new ArrayList<WSDLOperationFromBioCatalogueServiceDescription>();
+			for (Operation operation : operations) {
+				WSDLOperationFromBioCatalogueServiceDescription item;
+				try {
+					String operationName = operation.getName();
+					String operationDesc = parser.getOperationDocumentation(operationName);
+					String use = parser.getUse(operationName);
+					String style = parser.getStyle();
+					if (!WSDLActivityHealthChecker.checkStyleAndUse(style, use)) {
+						logger.warn("Unsupported style and use combination " + style + "/" + use + " for operation " + operationName + " from " + wsdlURL);
+						continue;
+					}
+					item = new WSDLOperationFromBioCatalogueServiceDescription(wsdlURL, operationName, operationDesc);
+					items.add(item);					
+				} catch (UnknownOperationException e) {
+					errorMessage = "Encountered an unexpected operation name:"
+							+ operation.getName();
+					ex = e;
+				}
+			}
+		} catch (ParserConfigurationException e) {
+			errorMessage = "Error configuring the WSDL parser";
+			ex = e;
+		} catch (WSDLException e) {
+			errorMessage = "There was an error with the wsdl: " + wsdlURL;
+			ex = e;
+		} catch (IOException e) {
+			errorMessage = "There was an IO error parsing the wsdl: " + wsdlURL
+					+ " Possible reason: the wsdl location was incorrect.";
+			ex = e;
+		} catch (SAXException e) {
+			errorMessage = "There was an error with the XML in the wsdl: "
+					+ wsdlURL;
+			ex = e;
+		} catch (IllegalArgumentException e) { // a problem with the wsdl url
+			errorMessage = "There was an error with the wsdl: " + wsdlURL + " "
+					+ "Possible reason: the wsdl location was incorrect.";
+			ex = e;
+		} catch (Exception e) { // anything else we did not expect
+			errorMessage = "There was an error with the wsdl: " + wsdlURL;
+			ex = e;
+		}
+		
+		if (callBack == null) {
+			if (errorMessage != null){
+				logger.error(errorMessage, ex);
+				return false;
+			}
+			else{
+				// We are not adding service through Taverna service registry's callback and
+				// findServiceDescriptionsAsync() -
+				// we are adding directly from the BioCatalogue perspective.
+				ServiceDescriptionRegistryImpl serviceDescriptionRegistry = ServiceDescriptionRegistryImpl
+						.getInstance();
+				for (WSDLOperationFromBioCatalogueServiceDescription item : items) {
+					serviceDescriptionRegistry
+							.addServiceDescriptionProvider(new BioCatalogueWSDLOperationServiceProvider(
+									item));
+				}
+				return true;
+			}
+		} else {
+			if (errorMessage != null){
+				callBack.fail(errorMessage, ex);
+				return false;
+			}
+			else{
+				callBack.status("Found " + operations.size() + " WSDL operations of service "
+						+ wsdlURL);
+				callBack.partialResults(items);
+				callBack.finished();
+				return true;
+			}
+		}   
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/RESTFromBioCatalogueServiceDescription.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/RESTFromBioCatalogueServiceDescription.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/RESTFromBioCatalogueServiceDescription.java
new file mode 100644
index 0000000..1551294
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/RESTFromBioCatalogueServiceDescription.java
@@ -0,0 +1,194 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.service_panel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.Icon;
+
+import net.sf.taverna.t2.lang.beans.PropertyAnnotation;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+
+import net.sf.taverna.t2.activities.rest.RESTActivity;
+import net.sf.taverna.t2.activities.rest.RESTActivity.DATA_FORMAT;
+import net.sf.taverna.t2.activities.rest.RESTActivity.HTTP_METHOD;
+import net.sf.taverna.t2.activities.rest.RESTActivityConfigurationBean;
+import net.sf.taverna.t2.activities.rest.ui.servicedescription.RESTActivityIcon;
+
+/**
+ * This class is solely intended to support import of REST services from BioCatalogue.
+ * 
+ * @author Sergejs Aleksejevs
+ */
+/*******************************************************************************
+ * Copyright (C) 2008-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
+ ******************************************************************************/
+public class RESTFromBioCatalogueServiceDescription extends ServiceDescription<RESTActivityConfigurationBean>
+{
+  private static final int SHORT_DESCRIPTION_MAX_LENGTH = 200;
+  
+  private static final String FULL_DESCRIPTION = "Full description";
+  
+  public static final int AMBIGUOUS_ACCEPT_HEADER_VALUE = 100;
+  public static final int DEFAULT_ACCEPT_HEADER_VALUE = 110;
+  public static final int AMBIGUOUS_CONTENT_TYPE_HEADER_VALUE = 200;
+  public static final int DEFAULT_CONTENT_TYPE_HEADER_VALUE = 210;
+  
+  
+	private RESTActivityConfigurationBean serviceConfigBean;
+	private String serviceName;
+	private String description;
+	
+	private List<Integer> dataWarnings;
+	
+	
+	/**
+	 * Constructor instantiates config bean and pre-populates
+	 * it with default values.
+	 */
+	public RESTFromBioCatalogueServiceDescription()
+	{
+	  // apply default name in case it won't be set manually later
+	  this.serviceName = "REST Service";
+	  this.serviceConfigBean = RESTActivityConfigurationBean.getDefaultInstance();
+	  this.dataWarnings = new ArrayList<Integer>();
+	}
+  
+  /**
+	 * The subclass of Activity which should be instantiated when adding a service
+	 * for this description.
+	 */
+	@Override
+	public Class<? extends Activity<RESTActivityConfigurationBean>> getActivityClass() {
+		return RESTActivity.class;
+	}
+
+	/**
+	 * The configuration bean which is to be used for configuring the instantiated activity.
+	 * 
+	 * Values are to be set through individual setters provided in this class.
+	 */
+	@Override
+	public RESTActivityConfigurationBean getActivityConfiguration() {
+		return serviceConfigBean;
+	}
+
+	/**
+	 * An icon to represent this service type in the service palette.
+	 */
+	@Override
+	public Icon getIcon() {
+	  return RESTActivityIcon.getRESTActivityIcon();
+	}
+
+	/**
+	 * The display name that will be shown in service palette and will
+	 * be used as a template for processor name when added to workflow.
+	 */
+	@Override
+	public String getName() {
+		return serviceName;
+	}
+	
+	
+	/**
+   * Truncates the description if necessary to {@link WSDLOperationFromBioCatalogueServiceDescription#SHORT_DESCRIPTION_MAX_LENGTH} --
+   * to get full description, use {@link WSDLOperationFromBioCatalogueServiceDescription#getFullDescription()}
+   */
+  public String getDescription() {
+    if (this.description != null && this.description.length() > SHORT_DESCRIPTION_MAX_LENGTH) {
+      return (this.description.substring(0, SHORT_DESCRIPTION_MAX_LENGTH) + "(...)");
+    }
+    else {
+      return this.description;
+    }
+  }
+  
+  @PropertyAnnotation(displayName = FULL_DESCRIPTION)
+  public String getFullDescription() {
+    return this.description;
+  }
+	
+
+	/**
+	 * The path to this service description in the service palette. Folders
+	 * will be created for each element of the returned path.
+	 * 
+	 * (Shouldn't really be ever used, as instances of different type are
+	 *  added into the Service Panel).
+	 */
+	@Override
+	public List<String> getPath() {
+		// For deeper paths you may return several strings
+		return Arrays.asList(BioCatalogueRESTServiceProvider.PROVIDER_NAME, "REST @ " + serviceConfigBean.getUrlSignature());
+	}
+
+	/**
+	 * Return a list of data values uniquely identifying this service
+	 * description (to avoid duplicates). Include only primary key like fields,
+	 * ie. ignore descriptions, icons, etc.
+	 */
+	@Override
+	protected List<? extends Object> getIdentifyingData() {
+		return Arrays.<Object>asList(serviceConfigBean.getUrlSignature(), serviceConfigBean.getHttpMethod());
+	}
+	
+	
+	public List<Integer> getDataWarnings() {
+	  return dataWarnings;
+	}
+	
+	
+	public void setURLSignature(String urlSignature) {
+	  this.serviceConfigBean.setUrlSignature(urlSignature);
+	}
+	
+	
+	public void setHttpMethod(HTTP_METHOD httpMethod) {
+    this.serviceConfigBean.setHttpMethod(httpMethod);
+  }
+	
+	
+	public void setAcceptHeaderValue(String acceptHeaderValue) {
+    this.serviceConfigBean.setAcceptsHeaderValue(acceptHeaderValue);
+  }
+	
+	
+	public void setOutgoingContentType(String outgoingContentType) 
+	{
+    this.serviceConfigBean.setUrlSignature(outgoingContentType);
+    
+    // automatically infer data format - string/binary from the content type
+    if (outgoingContentType.startsWith("text")) { this.serviceConfigBean.setOutgoingDataFormat(DATA_FORMAT.String); }
+    else { this.serviceConfigBean.setOutgoingDataFormat(DATA_FORMAT.Binary); }
+  }
+	
+	
+	public void setServiceName(String name) {
+	  this.serviceName = name;
+	}
+	
+	
+	public void setDescription(String description) {
+	  this.description = description;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/WSDLOperationFromBioCatalogueServiceDescription.java
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/WSDLOperationFromBioCatalogueServiceDescription.java b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/WSDLOperationFromBioCatalogueServiceDescription.java
new file mode 100644
index 0000000..f5de088
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/java/net/sf/taverna/t2/ui/perspectives/biocatalogue/integration/service_panel/WSDLOperationFromBioCatalogueServiceDescription.java
@@ -0,0 +1,116 @@
+package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.service_panel;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.Icon;
+
+import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
+import net.sf.taverna.t2.activities.wsdl.WSDLActivityConfigurationBean;
+import net.sf.taverna.t2.activities.wsdl.servicedescriptions.WSDLActivityIcon;
+import net.sf.taverna.t2.lang.beans.PropertyAnnotation;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+
+/*******************************************************************************
+ * Copyright (C) 2008-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
+ ******************************************************************************/
+public class WSDLOperationFromBioCatalogueServiceDescription extends ServiceDescription<WSDLActivityConfigurationBean>
+{
+  private static final int SHORT_DESCRIPTION_MAX_LENGTH = 200;
+  
+  private static final String FULL_DESCRIPTION = "Full description";
+  
+  
+  private final String wsdlLocation;
+  private final String operationName;
+  private final String description;
+  
+  
+  public WSDLOperationFromBioCatalogueServiceDescription(String wsdlLocation, String operationName, String description)
+  {
+    this.wsdlLocation = wsdlLocation;
+    this.operationName = operationName;
+    this.description = description;
+  }
+  
+  public WSDLOperationFromBioCatalogueServiceDescription(SoapOperationIdentity soapOpearationIdentity)
+  {
+    this.wsdlLocation = soapOpearationIdentity.getWsdlLocation();
+    this.operationName = soapOpearationIdentity.getOperationName();
+    this.description = soapOpearationIdentity.getDescription();
+  }
+  
+  
+	@Override
+	public Class getActivityClass() {
+		return WSDLActivity.class;
+	}
+
+	@Override
+	public WSDLActivityConfigurationBean getActivityConfiguration() {
+		WSDLActivityConfigurationBean bean = new WSDLActivityConfigurationBean();
+		bean.setOperation(operationName);
+		bean.setWsdl(wsdlLocation);
+		return bean;
+	}
+
+	@Override
+	public Icon getIcon() {
+		return WSDLActivityIcon.getWSDLIcon();
+	}
+
+	@Override
+	public String getName() {
+		return (this.operationName);
+	}
+
+	/**
+	 * Truncates the description if necessary to {@link WSDLOperationFromBioCatalogueServiceDescription#SHORT_DESCRIPTION_MAX_LENGTH} --
+	 * to get full description, use {@link WSDLOperationFromBioCatalogueServiceDescription#getFullDescription()}
+	 */
+	public String getDescription() {
+    if (this.description != null && this.description.length() > SHORT_DESCRIPTION_MAX_LENGTH) {
+      return (this.description.substring(0, SHORT_DESCRIPTION_MAX_LENGTH) + "(...)");
+    }
+    else {
+      return this.description;
+    }
+  }
+	
+	@PropertyAnnotation(displayName = FULL_DESCRIPTION)
+	public String getFullDescription() {
+	  return this.description;
+	}
+	
+	@Override
+	public List<String> getPath() {
+		return Arrays.asList(BioCatalogueWSDLOperationServiceProvider.PROVIDER_NAME, "WSDL @ " + this.wsdlLocation);
+	}
+	
+	@Override
+	protected List<? extends Object> getIdentifyingData()
+	{
+	  // This is important - Taverna won't add identical operations
+	  // into the Service Panel. These tokens distinguish added items.
+		return Arrays.asList(wsdlLocation, operationName);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
new file mode 100644
index 0000000..44cf82b
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
@@ -0,0 +1,2 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.service_panel.BioCatalogueWSDLOperationServiceProvider
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.service_panel.BioCatalogueRESTServiceProvider

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
new file mode 100644
index 0000000..8bdcfa5
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
@@ -0,0 +1,2 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.menus.BioCatalogueContextualMenuSection
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.menus.MenuActionProcessorHealthCheck
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI
new file mode 100644
index 0000000..b036654
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ShutdownSPI
@@ -0,0 +1 @@
+#net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentShutdownHook
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
new file mode 100644
index 0000000..bc9b362
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.config.BioCataloguePluginConfigurationUIFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.report.explainer.VisitExplainer
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.report.explainer.VisitExplainer b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.report.explainer.VisitExplainer
new file mode 100644
index 0000000..5b64699
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.report.explainer.VisitExplainer
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check.BioCatalogueWSDLActivityHealthCheckVisitExplainer
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
new file mode 100644
index 0000000..a26e638
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
@@ -0,0 +1,3 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.contextual_views.BioCataloguePluginProcessorContextViewFactory
+#net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.contextual_views.BioCataloguePluginInputPortContextViewFactory
+#net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.contextual_views.BioCataloguePluginOutputPortContextViewFactory

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI
new file mode 100644
index 0000000..eb7f253
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.BioCataloguePerspective

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
new file mode 100644
index 0000000..1c7d751
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
new file mode 100644
index 0000000..40b15c7
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponent

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
new file mode 100644
index 0000000..f24a3dd
--- /dev/null
+++ b/taverna-perspective-biocatalogue/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
@@ -0,0 +1 @@
+net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check.BioCatalogueWSDLActivityHealthChecker
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2-still.png
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2-still.png b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2-still.png
new file mode 100644
index 0000000..12abdf6
Binary files /dev/null and b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2-still.png differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2.gif
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2.gif b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2.gif
new file mode 100644
index 0000000..c4793ec
Binary files /dev/null and b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-grey-bert2.gif differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2-still.png
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2-still.png b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2-still.png
new file mode 100644
index 0000000..9b6784e
Binary files /dev/null and b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2-still.png differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2.gif
----------------------------------------------------------------------
diff --git a/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2.gif b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2.gif
new file mode 100644
index 0000000..c6745b9
Binary files /dev/null and b/taverna-perspective-biocatalogue/src/main/resources/net/sf/taverna/t2/ui/perspectives/biocatalogue/ajax-loader-orange-bert2.gif differ