package org.apache.taverna.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 org.apache.taverna.biocatalogue.model.SoapOperationIdentity; | |
import org.apache.taverna.biocatalogue.model.Util; | |
import org.apache.taverna.biocatalogue.model.connectivity.BioCatalogueClient; | |
import net.sf.taverna.t2.activities.wsdl.WSDLActivity; | |
import net.sf.taverna.t2.activities.wsdl.WSDLActivityConfigurationBean; | |
import org.apache.taverna.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; | |
} | |
} |