You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sa...@apache.org on 2014/04/14 20:31:17 UTC
[75/90] [abbrv] AIRAVATA-1124
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/WorkflowInvokerWrapperForGFacInvoker.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/WorkflowInvokerWrapperForGFacInvoker.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/WorkflowInvokerWrapperForGFacInvoker.java
new file mode 100644
index 0000000..9ca5669
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/WorkflowInvokerWrapperForGFacInvoker.java
@@ -0,0 +1,233 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.invoker;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.airavata.xbaya.jython.lib.ServiceNotifiable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.builder.XmlElement;
+
+import xsul.lead.LeadContextHeader;
+import xsul.wsif.WSIFMessage;
+
+public class WorkflowInvokerWrapperForGFacInvoker extends GFacInvoker {
+
+ private static final Logger logger = LoggerFactory.getLogger(WorkflowInvokerWrapperForGFacInvoker.class);
+
+ private ServiceNotifiable notifier;
+
+ private String serviceInformation;
+
+ private Future<Boolean> result;
+
+ protected boolean failerSent = false;
+
+ public WorkflowInvokerWrapperForGFacInvoker(QName portTypeQName, String gfacURL, String messageBoxURL,
+ LeadContextHeader leadcontext, ServiceNotifiable serviceNotificationSender) {
+ super(portTypeQName, gfacURL, messageBoxURL, leadcontext);
+ this.notifier = serviceNotificationSender;
+ this.serviceInformation = portTypeQName.toString();
+ }
+
+ /**
+ * @see org.apache.airavata.xbaya.invoker.WorkflowInvoker#invoke()
+ */
+ public synchronized boolean invoke() throws WorkflowException {
+
+ try {
+ WSIFMessage inputMessage = super.getInputs();
+ logger.debug("inputMessage: " + XMLUtil.xmlElementToString((XmlElement) inputMessage));
+ this.notifier.invokingService(inputMessage);
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ this.result = executor.submit(new Callable<Boolean>() {
+ @SuppressWarnings("boxing")
+ public Boolean call() {
+ try {
+ boolean success = WorkflowInvokerWrapperForGFacInvoker.super.invoke();
+ if (success) {
+ // Send notification
+ WSIFMessage outputMessage = WorkflowInvokerWrapperForGFacInvoker.super.getOutputs();
+ // An implementation of WSIFMessage,
+ // WSIFMessageElement, implements toString(), which
+ // serialize the message XML.
+ logger.debug("outputMessage: " + outputMessage);
+ WorkflowInvokerWrapperForGFacInvoker.this.notifier.serviceFinished(outputMessage);
+ } else {
+ WSIFMessage faultMessage = WorkflowInvokerWrapperForGFacInvoker.super.getFault();
+ // An implementation of WSIFMessage,
+ // WSIFMessageElement, implements toString(), which
+ // serialize the message XML.
+ logger.debug("received fault: " + faultMessage);
+ WorkflowInvokerWrapperForGFacInvoker.this.notifier.receivedFault(faultMessage);
+ WorkflowInvokerWrapperForGFacInvoker.this.failerSent = true;
+ }
+ return success;
+ } catch (WorkflowException e) {
+ logger.error(e.getMessage(), e);
+ // An appropriate message has been set in the exception.
+ WorkflowInvokerWrapperForGFacInvoker.this.notifier.invocationFailed(e.getMessage(), e);
+ WorkflowInvokerWrapperForGFacInvoker.this.failerSent = true;
+ throw new WorkflowRuntimeException(e);
+ } catch (RuntimeException e) {
+ logger.error(e.getMessage(), e);
+ String message = "Error in invoking a service: "
+ + WorkflowInvokerWrapperForGFacInvoker.this.serviceInformation;
+ WorkflowInvokerWrapperForGFacInvoker.this.notifier.invocationFailed(message, e);
+ WorkflowInvokerWrapperForGFacInvoker.this.failerSent = true;
+ throw e;
+ }
+ }
+ });
+
+ // Kill the thread inside of executor. This is necessary for Jython
+ // script to finish.
+ executor.shutdown();
+
+ // Let other threads know that job has been submitted.
+ notifyAll();
+
+ // Check if the invocation itself fails. This happens immediately.
+ try {
+ this.result.get(100, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ logger.error(e.getMessage(), e);
+ } catch (TimeoutException e) {
+ // The job is probably running fine.
+ // The normal case.
+ return true;
+ } catch (ExecutionException e) {
+ // The service-failed notification should have been sent
+ // already.
+ logger.error(e.getMessage(), e);
+ String message = "Error in invoking a service: " + this.serviceInformation;
+ throw new WorkflowException(message, e);
+ }
+ } catch (RuntimeException e) {
+ logger.error(e.getMessage(), e);
+ String message = "Error in invoking a service: " + this.serviceInformation;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ } catch (Error e) {
+ logger.error(e.getMessage(), e);
+ String message = "Unexpected error: " + this.serviceInformation;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ }
+
+ boolean success = super.invoke();
+ if (!success) {
+ try {
+ throw new Exception("Failed invoking GFac");
+ } catch (Exception e) {
+ notifier.invocationFailed(super.getFault().toString(), e);
+ }
+
+ } else {
+ notifier.serviceFinished(super.getOutputs());
+ }
+ return success;
+ }
+
+ public synchronized void waitToFinish() throws WorkflowException {
+ try {
+ while (this.result == null) {
+ // The job is not submitted yet.
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ // Wait for the job to finish.
+ Boolean success = this.result.get();
+ if (success == false) {
+ WSIFMessage faultMessage = super.getFault();
+ String message = "Error in a service: ";
+ // An implementation of WSIFMessage,
+ // WSIFMessageElement, implements toString(), which
+ // serialize the message XML.
+ message += faultMessage.toString();
+ throw new WorkflowException(message);
+ }
+ } catch (InterruptedException e) {
+ logger.error(e.getMessage(), e);
+ } catch (ExecutionException e) {
+ // The service-failed notification should have been sent already.
+ logger.error(e.getMessage(), e);
+ String message = "Error in invoking a service: " + this.serviceInformation;
+ throw new WorkflowException(message, e);
+ } catch (RuntimeException e) {
+ logger.error(e.getMessage(), e);
+ String message = "Error while waiting for a service to finish: " + this.serviceInformation;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ } catch (Error e) {
+ logger.error(e.getMessage(), e);
+ String message = "Unexpected error: " + this.serviceInformation;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ }
+ }
+
+ public Object getOutput(String name) throws WorkflowException {
+ try {
+ waitToFinish();
+ Object output = super.getOutput(name);
+ if (output instanceof XmlElement) {
+ logger.debug("output: " + XMLUtil.xmlElementToString((XmlElement) output));
+ }
+ return output;
+ } catch (WorkflowException e) {
+ logger.error(e.getMessage(), e);
+ // An appropriate message has been set in the exception.
+ if (!this.failerSent) {
+ this.notifier.invocationFailed(e.getMessage(), e);
+ }
+ throw e;
+ } catch (RuntimeException e) {
+ logger.error(e.getMessage(), e);
+ String message = "Error while waiting for a output: " + name;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ } catch (Error e) {
+ logger.error(e.getMessage(), e);
+ String message = "Unexpected error: " + this.serviceInformation;
+ this.notifier.invocationFailed(message, e);
+ throw new WorkflowException(message, e);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/factory/InvokerFactory.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/factory/InvokerFactory.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/factory/InvokerFactory.java
new file mode 100644
index 0000000..75d5677
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/invoker/factory/InvokerFactory.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.invoker.factory;
+
+import javax.xml.namespace.QName;
+
+import org.apache.airavata.common.workflow.execution.context.WorkflowContextHeaderBuilder;
+import org.apache.airavata.common.utils.WSDLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.xbaya.invoker.AsynchronousInvoker;
+import org.apache.airavata.xbaya.invoker.GFacInvoker;
+import org.apache.airavata.xbaya.invoker.Invoker;
+import org.apache.airavata.xbaya.invoker.SimpleInvoker;
+
+import xsul.lead.LeadContextHeader;
+import xsul.wsdl.WsdlDefinitions;
+
+public class InvokerFactory {
+
+ /**
+ * @param portTypeQName
+ * @param definitions
+ * @param gfacURL
+ * @param messageBoxURL
+ * @return The invoker
+ * @throws WorkflowException
+ */
+ public static Invoker createInvoker(QName portTypeQName, WsdlDefinitions definitions, String gfacURL,
+ String messageBoxURL, LeadContextHeader leadContext) throws WorkflowException {
+ Invoker invoker = null;
+
+ if (definitions != null && definitions.getServices().iterator().hasNext()) {
+ // check if this web service supports asynchronous invocation
+ if (WSDLUtil.isAsynchronousSupported(WSDLUtil.wsdlDefinitions3ToWsdlDefintions5(definitions))) {
+ invoker = new AsynchronousInvoker(definitions, messageBoxURL);
+ } else {
+ invoker = new SimpleInvoker(definitions);
+ }
+ } else if (gfacURL != null && gfacURL.length() != 0) {
+ invoker = new GFacInvoker(portTypeQName, gfacURL, messageBoxURL, leadContext);
+ }
+
+ if (invoker == null) {
+ String message = "Cannot find an appropriate way to invoke the service";
+ throw new WorkflowException(message);
+ }
+ return invoker;
+ }
+
+ public static Invoker createInvoker(QName portTypeQName, WsdlDefinitions definitions, String gfacURL,
+ String messageBoxURL, WorkflowContextHeaderBuilder builder, boolean differ) throws WorkflowException {
+ Invoker invoker = null;
+
+ if (definitions != null && definitions.getServices().iterator().hasNext()) {
+ // check if this web service supports asynchronous invocation
+ if (WSDLUtil.isAsynchronousSupported(WSDLUtil.wsdlDefinitions3ToWsdlDefintions5(definitions))) {
+ invoker = new AsynchronousInvoker(definitions, messageBoxURL);
+ } else {
+ invoker = new SimpleInvoker(definitions);
+ }
+ } else if (gfacURL != null && gfacURL.length() != 0) {
+ invoker = new GFacInvoker(portTypeQName, gfacURL, messageBoxURL, builder);
+ }
+
+ if (invoker == null) {
+ String message = "Cannot find an appropriate way to invoke the service";
+ throw new WorkflowException(message);
+ }
+ return invoker;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/GFacServiceCreator.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/GFacServiceCreator.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/GFacServiceCreator.java
new file mode 100644
index 0000000..66685ba
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/GFacServiceCreator.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.v1.builder.XmlElement;
+
+import xsul.wsdl.WsdlDefinitions;
+import xsul.wsdl.WsdlResolver;
+import xsul.wsif.WSIFMessage;
+import xsul.wsif.WSIFOperation;
+import xsul.wsif.WSIFPort;
+import xsul.wsif.WSIFService;
+import xsul.wsif.WSIFServiceFactory;
+import xsul.wsif.spi.WSIFProviderManager;
+
+public class GFacServiceCreator {
+
+ private static final String CREATE_SERVICE_OPERATION = "CreateService";
+
+ private static final String SHUTDOWN_OPERATION = "Shutdown";
+
+ private static final String SERVICE_QNAME_PART = "serviceQName";
+
+ private static final String SECURITY_PART = "security";
+
+ private static final String WSDL_PART = "WSDL";
+
+ private static final String SECURITY_NONE = "None";
+
+ private static final Logger logger = LoggerFactory.getLogger(GFacServiceCreator.class);
+
+ private WSIFOperation gFacOperation;
+
+ private WsdlDefinitions serviceDefinitions;
+
+ static {
+ WSIFProviderManager.getInstance().addProvider(new xsul.wsif_xsul_soap_http.Provider());
+ }
+
+ /**
+ * Constructs a GFacServiceCreater.
+ *
+ * @param wsdlURL
+ * The URL of the GFac service
+ * @throws URISyntaxException
+ * @throws WorkflowException
+ */
+ public GFacServiceCreator(String wsdlURL) throws URISyntaxException, WorkflowException {
+ this(new URI(wsdlURL));
+ }
+
+ /**
+ * Constructs a GFacServiceCreater.
+ *
+ * @param wsdlURI
+ * The URI of the GFac service
+ * @throws WorkflowException
+ */
+ public GFacServiceCreator(URI wsdlURI) throws WorkflowException {
+ try {
+ WsdlDefinitions definitions = WsdlResolver.getInstance().loadWsdl(wsdlURI);
+ WSIFService service = WSIFServiceFactory.newInstance().getService(definitions);
+ WSIFPort port = service.getPort();
+ this.gFacOperation = port.createOperation(CREATE_SERVICE_OPERATION);
+ } catch (RuntimeException e) {
+ String message = "Failed to connect to the Generic Factory: " + wsdlURI;
+ throw new WorkflowException(message, e);
+ }
+ }
+
+ /**
+ * @param serviceQName
+ * @return The WSDL definitions of the service created.
+ * @throws WorkflowException
+ */
+ public WsdlDefinitions createService(QName serviceQName) throws WorkflowException {
+ return createService(serviceQName.toString());
+ }
+
+ /**
+ * @param serviceQName
+ * @return The WSDL definitions of the service created.
+ * @throws WorkflowException
+ */
+ public WsdlDefinitions createService(String serviceQName) throws WorkflowException {
+ logger.debug(serviceQName);
+ try {
+ WSIFMessage inputMessage = this.gFacOperation.createInputMessage();
+ WSIFMessage outputMessage = this.gFacOperation.createOutputMessage();
+ WSIFMessage faultMessage = this.gFacOperation.createFaultMessage();
+
+ inputMessage.setObjectPart(SERVICE_QNAME_PART, serviceQName);
+ inputMessage.setObjectPart(SECURITY_PART, SECURITY_NONE);
+
+ logger.debug("inputMessage: " + inputMessage);
+ boolean success = this.gFacOperation.executeRequestResponseOperation(inputMessage, outputMessage,
+ faultMessage);
+ if (!success) {
+ // An implementation of WSIFMessage, WSIFMessageElement,
+ // implements toString(), which serialize the message XML.
+ String message = "Failed to create a service: " + faultMessage.toString();
+ throw new WorkflowException(message);
+ }
+
+ String wsdl = (String) outputMessage.getObjectPart(WSDL_PART);
+ logger.debug("WSDL: " + wsdl);
+
+ XmlElement definitionsElement = XMLUtil.stringToXmlElement3(wsdl);
+
+ this.serviceDefinitions = new WsdlDefinitions(definitionsElement);
+ return this.serviceDefinitions;
+ } catch (RuntimeException e) {
+ String message = "Failed to create a service";
+ throw new WorkflowException(message, e);
+ }
+ }
+
+ /**
+ * Shutdowns the service created.
+ *
+ * @throws WorkflowException
+ */
+ public void shutdownService() throws WorkflowException {
+ WSIFService service = WSIFServiceFactory.newInstance().getService(this.serviceDefinitions);
+ WSIFPort port = service.getPort();
+ WSIFOperation operation = port.createOperation(SHUTDOWN_OPERATION);
+
+ WSIFMessage inputMessage = operation.createInputMessage();
+ WSIFMessage outputMessage = operation.createOutputMessage();
+ WSIFMessage faultMessage = operation.createFaultMessage();
+
+ boolean success = operation.executeRequestResponseOperation(inputMessage, outputMessage, faultMessage);
+ if (!success) {
+ // An implementation of WSIFMessage, WSIFMessageElement,
+ // implements toString(), which serialize the message XML.
+ String message = "Failed to shutdown the service: " + faultMessage.toString();
+ throw new WorkflowException(message);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/NotificationSender.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/NotificationSender.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/NotificationSender.java
new file mode 100644
index 0000000..f478e18
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/NotificationSender.java
@@ -0,0 +1,289 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.apache.airavata.common.utils.StringUtil;
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.tracking.NotifierFactory;
+import org.apache.airavata.workflow.tracking.WorkflowNotifier;
+import org.apache.airavata.workflow.tracking.common.InvocationContext;
+import org.apache.airavata.workflow.tracking.common.InvocationEntity;
+import org.apache.airavata.workflow.tracking.common.WorkflowTrackingContext;
+import org.apache.axis2.addressing.EndpointReference;
+import org.python.core.PyObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+public class NotificationSender implements WorkflowNotifiable {
+
+ protected static final Logger logger = LoggerFactory.getLogger(NotificationSender.class);
+
+ protected WorkflowNotifier notifier;
+
+ protected String brokerURL;
+
+ protected String topic;
+
+ protected URI workflowID;
+
+ protected InvocationEntity initiator;
+
+ protected InvocationEntity receiver;
+
+ protected InvocationContext invocationContext;
+
+ protected EndpointReference eventSink;
+
+ protected WorkflowTrackingContext context;
+
+ /**
+ * Constructs a NotificationSender.
+ *
+ * @param brokerURL
+ * @param topic
+ */
+ public NotificationSender(URI brokerURL, String topic) {
+ this(brokerURL.toString(), topic);
+ }
+
+ /**
+ * Creates a NotificationSender.
+ *
+ * @param brokerURL
+ * The location of notification brokerUrl.
+ * @param topic
+ * The notification topic.
+ */
+ public NotificationSender(String brokerURL, String topic) {
+ logger.debug("brokerURL:" + brokerURL + "topic:" + topic);
+ this.topic = topic;
+ this.brokerURL = brokerURL;
+ this.workflowID = URI.create(StringUtil.convertToJavaIdentifier(this.topic));
+ this.eventSink = new EndpointReference(this.brokerURL);
+ Properties props = new Properties();
+
+ this.notifier = NotifierFactory.createNotifier();
+ URI initiatorWorkflowID = null;
+ URI initiatorServiceID = URI.create(StringUtil.convertToJavaIdentifier(topic));
+ String initiatorWorkflowNodeID = null;
+ Integer initiatorWorkflowTimeStep = null;
+ this.context = this.notifier.createTrackingContext(props, brokerURL, initiatorWorkflowID, initiatorServiceID,
+ initiatorWorkflowNodeID, initiatorWorkflowTimeStep);
+ this.context.setTopic(topic);
+ this.initiator = this.notifier.createEntity(initiatorWorkflowID, initiatorServiceID, initiatorWorkflowNodeID,
+ initiatorWorkflowTimeStep);
+
+ URI receiverWorkflowID = this.workflowID;
+ URI receiverServiceID = this.workflowID;
+ String receiverWorkflowNodeID = null;
+ Integer receiverWorkflowTimeStep = null;
+ this.receiver = this.notifier.createEntity(receiverWorkflowID, receiverServiceID, receiverWorkflowNodeID,
+ receiverWorkflowTimeStep);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#getEventSink()
+ */
+ @Override
+ public EndpointReference getEventSink() {
+ return this.eventSink;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowStarted(org.python.core.PyObject[],
+ * java.lang.String[])
+ */
+ @Override
+ public void workflowStarted(PyObject[] args, String[] keywords) {
+ String message = "";
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0) {
+ message += ", ";
+ }
+ message += keywords[i] + "=" + args[i];
+ }
+ this.invocationContext = this.notifier.workflowInvoked(this.context, this.initiator, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowStarted(java.lang.Object[],
+ * java.lang.String[])
+ */
+ @Override
+ public void workflowStarted(Object[] args, String[] keywords) {
+ String message = "";
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0) {
+ message += ", ";
+ }
+ message += keywords[i] + "=" + args[i];
+ }
+ this.invocationContext = this.notifier.workflowInvoked(this.context, this.initiator, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowFinished(java.lang.Object[],
+ * java.lang.String[])
+ */
+ @Override
+ public void workflowFinished(Object[] args, String[] keywords) {
+ String message = "";
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0) {
+ message += ", ";
+ }
+ message += keywords[i] + "=" + args[i];
+ }
+ this.notifier.sendingResult(context, this.invocationContext, message);
+ this.notifier.workflowTerminated(context, this.workflowID, "Workflow finished successfully.");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#sendingPartialResults(java.lang.Object[],
+ * java.lang.String[])
+ */
+ @Override
+ public void sendingPartialResults(Object[] args, String[] keywords) {
+ String message = "";
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0) {
+ message += ", ";
+ }
+ message += keywords[i] + "=" + args[i];
+ }
+ this.notifier.sendingResult(context, this.invocationContext, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowFinished(org.python.core.PyObject[],
+ * java.lang.String[])
+ */
+ @Override
+ public void workflowFinished(PyObject[] args, String[] keywords) {
+ String message = "";
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0) {
+ message += ", ";
+ }
+ message += keywords[i] + "=" + args[i];
+ }
+ this.notifier.sendingResult(context, this.invocationContext, message);
+ this.notifier.workflowTerminated(context, this.workflowID, "Workflow Execution Finished.");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowTerminated()
+ */
+ @Override
+ public void workflowTerminated() {
+ this.notifier.workflowTerminated(context, this.workflowID, "Workflow Execution Finished.");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowFailed(java.lang.String)
+ */
+ @Override
+ public void workflowFailed(String message) {
+ workflowFailed(message, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowFailed(java.lang.Throwable)
+ */
+ @Override
+ public void workflowFailed(Throwable e) {
+ workflowFailed(null, e);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#workflowFailed(java.lang.String,
+ * java.lang.Throwable)
+ */
+ @Override
+ public void workflowFailed(String message, Throwable e) {
+ if(e != null)
+ logger.error(e.getMessage(), e);
+ if (message == null || "".equals(message)) {
+ message = "Error";
+ }
+ if (e != null) {
+ message += ": " + e.toString();
+ }
+ if (e != null) {
+ String stackTrace = StringUtil.getStackTraceInString(e);
+ XmlElement stackTraceElement = XMLUtil.BUILDER.newFragment("stackTrace");
+ stackTraceElement.addChild(stackTrace);
+ this.notifier.sendingFault(context, this.invocationContext, message,
+ XMLUtil.xmlElementToString(stackTraceElement));
+ } else {
+ this.notifier.sendingFault(context, this.invocationContext, message);
+ }
+ }
+
+ public void info(String message) {
+ this.notifier.info(context, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.WorkflowNotifiable#createServiceNotificationSender(java.lang.String)
+ */
+ @Override
+ public ServiceNotifiable createServiceNotificationSender(String nodeID) {
+ return new ServiceNotificationSender(this.notifier, this.eventSink, this.initiator, this.workflowID, nodeID,
+ this.context,this.invocationContext);
+ }
+
+ @Override
+ public void cleanup(){
+ this.notifier.delete();
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotifiable.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotifiable.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotifiable.java
new file mode 100644
index 0000000..1865d9c
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotifiable.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import java.net.URI;
+
+import org.apache.axis2.addressing.EndpointReference;
+
+import xsul.wsif.WSIFMessage;
+
+public interface ServiceNotifiable {
+
+ /**
+ * @param serviceID
+ */
+ public abstract void setServiceID(String serviceID);
+
+ /**
+ * @return The event sink.
+ */
+ public abstract EndpointReference getEventSink();
+
+ /**
+ * @return The workflow ID.
+ */
+ public abstract URI getWorkflowID();
+
+ /**
+ * @param inputs
+ */
+ public abstract void invokingService(WSIFMessage inputs);
+
+ /**
+ * @param outputs
+ */
+ public abstract void serviceFinished(WSIFMessage outputs);
+
+ /**
+ * Sends an InvokeServiceFinishedFailed notification message.
+ *
+ * @param message
+ * The message to send
+ * @param e
+ */
+ public abstract void invocationFailed(String message, Throwable e);
+
+ /**
+ * Sends a receivedFault notification message.
+ *
+ * @param message
+ * The message to send
+ */
+ @Deprecated
+ public abstract void receivedFault(String message);
+
+ /**
+ * Sends a receivedFault notification message.
+ *
+ * @param fault
+ */
+ public abstract void receivedFault(WSIFMessage fault);
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotificationSender.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotificationSender.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotificationSender.java
new file mode 100644
index 0000000..36b79bf
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/ServiceNotificationSender.java
@@ -0,0 +1,293 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import java.net.URI;
+import java.util.Iterator;
+
+import org.apache.airavata.common.utils.StringUtil;
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.tracking.WorkflowNotifier;
+import org.apache.airavata.workflow.tracking.common.InvocationContext;
+import org.apache.airavata.workflow.tracking.common.InvocationEntity;
+import org.apache.airavata.workflow.tracking.common.WorkflowTrackingContext;
+import org.apache.airavata.workflow.tracking.impl.state.InvocationContextImpl;
+import org.apache.axis2.addressing.EndpointReference;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+import xsul.wsif.WSIFMessage;
+
+public class ServiceNotificationSender implements ServiceNotifiable {
+
+ private static final Logger logger = LoggerFactory.getLogger(ServiceNotificationSender.class);
+
+ private WorkflowNotifier notifier;
+
+ private URI workflowID;
+
+ private String nodeID;
+
+ private String serviceID;
+
+ private InvocationEntity receiver;
+
+ private InvocationEntity initiator;
+
+ private InvocationContext invocationContext;
+
+ private WorkflowTrackingContext context;
+
+ private EndpointReference eventSink;
+
+ /**
+ * Constructs a ServiceNotificationSender.
+ *
+ * @param notifier
+ * @param eventSink
+ * @param initiator
+ * @param workflowID
+ * @param nodeID
+ */
+ protected ServiceNotificationSender(WorkflowNotifier notifier, EndpointReference eventSink,
+ InvocationEntity initiator, URI workflowID, String nodeID, WorkflowTrackingContext context, InvocationContext invocationContext) {
+ this.notifier = notifier;
+ this.eventSink = eventSink;
+ this.initiator = initiator;
+ this.workflowID = workflowID;
+ this.nodeID = nodeID;
+ this.context = context;
+ // In case of creating a service on the fly, there is no serviceID at
+ // the beginning.
+ this.serviceID = "";
+ this.invocationContext = invocationContext;
+ URI receiverWorkflowID = this.workflowID;
+ URI receiverServiceID = URI.create(this.serviceID);
+ String receiverWorkflowNodeID = this.nodeID;
+ Integer workflowTimeStep = new Integer(0);
+ this.receiver = this.notifier.createEntity(receiverWorkflowID, receiverServiceID, receiverWorkflowNodeID,
+ workflowTimeStep);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#setServiceID(java.lang.String)
+ */
+ @Override
+ public void setServiceID(String serviceID) {
+ logger.debug("SerivceID:" + serviceID);
+ this.serviceID = serviceID;
+
+ URI receiverWorkflowID = this.workflowID;
+ URI receiverServiceID = URI.create(this.serviceID);
+ String receiverWorkflowNodeID = this.nodeID;
+ Integer workflowTimeStep = new Integer(0);
+ this.receiver = this.notifier.createEntity(receiverWorkflowID, receiverServiceID, receiverWorkflowNodeID,
+ workflowTimeStep);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#getEventSink()
+ */
+ @Override
+ public EndpointReference getEventSink() {
+ return this.eventSink;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#getWorkflowID()
+ */
+ @Override
+ public URI getWorkflowID() {
+ return this.workflowID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#invokingService(xsul.wsif.WSIFMessage)
+ */
+ @Override
+ public void invokingService(WSIFMessage inputs) {
+ String message = "";
+ Iterator partIt = inputs.partNames().iterator();
+ boolean first = true;
+ while (partIt.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ message += ", ";
+ }
+
+ String name = (String) partIt.next();
+ Object value = inputs.getObjectPart(name);
+ if(value instanceof org.xmlpull.v1.builder.XmlElement){
+ message += name + "=";
+ Iterator children = ((org.xmlpull.v1.builder.XmlElement) value).children();
+ while (children.hasNext()){
+ message += children.next();
+ }
+ }else{
+ message += name + "=" + value;
+ }
+ }
+ XmlObject header = null;
+ XmlObject body;
+ try {
+ body = XmlObject.Factory.parse(inputs.toString());
+ } catch (XmlException e) {
+ logger.warn("Failed to parse " + inputs.toString(), e);
+ body = null; // Send notification anyway.
+ }
+ this.invocationContext = this.notifier.invokingService(this.context, this.receiver, header, body, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#serviceFinished(xsul.wsif.WSIFMessage)
+ */
+ @Override
+ public void serviceFinished(WSIFMessage outputs) {
+ String message = "";
+ Iterator partIt = outputs.partNames().iterator();
+ boolean first = true;
+ while (partIt.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ message += ", ";
+ }
+ String name = (String) partIt.next();
+ Object value = outputs.getObjectPart(name);
+ if(value instanceof org.xmlpull.v1.builder.XmlElement){
+ message += name + "=";
+ Iterator children = ((org.xmlpull.v1.builder.XmlElement) value).children();
+ while (children.hasNext()){
+ message += children.next();
+ }
+ }else{
+ message += name + "=" + value;
+ }
+ }
+ XmlObject header = null;
+ XmlObject body;
+ try {
+ body = XmlObject.Factory.parse(outputs.toString());
+ } catch (XmlException e) {
+ logger.warn("Failed to parse " + outputs.toString(), e);
+ body = null; // Send notification anyway.
+ }
+ this.notifier.receivedResult(this.context, this.invocationContext, header, body, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#invocationFailed(java.lang.String,
+ * java.lang.Throwable)
+ */
+ @Override
+ public void invocationFailed(String message, Throwable e) {
+
+ // TODO there are two types of error messages.
+ // The first one is while creating a service. (No API)
+ // The second is while invoking a service.
+ // e.g. notifier.invokingServiceFailed().
+
+ // XXX If error occurs before invoking a service, create a fake
+ // invocation context.
+ if (this.invocationContext == null) {
+ this.invocationContext = new InvocationContextImpl(this.initiator, this.receiver);
+ }
+
+ logger.error(e.getMessage(), e);
+ if (message == null || "".equals(message)) {
+ message = "Error";
+ }
+ if (e != null) {
+ message += ": " + e.toString();
+ }
+ if (e != null) {
+ String stackTrace = StringUtil.getStackTraceInString(e);
+ XmlElement stackTraceElement = XMLUtil.BUILDER.newFragment("stackTrace");
+ stackTraceElement.addChild(stackTrace);
+ String annotation = XMLUtil.xmlElementToString(stackTraceElement);
+ this.notifier.invokingServiceFailed(this.context, this.invocationContext, e, message, annotation);
+ } else {
+ this.notifier.invokingServiceFailed(this.context, this.invocationContext, message);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#receivedFault(java.lang.String)
+ */
+ @Override
+ @Deprecated
+ public void receivedFault(String message) {
+ // XXX If error occurs before invoking a service, create a fake
+ // invocation context.
+ if (this.invocationContext == null) {
+ this.invocationContext = new InvocationContextImpl(this.initiator, this.receiver);
+ }
+
+ if (message == null || "".equals(message)) {
+ message = "Error";
+ }
+ this.notifier.receivedFault(this.context, this.invocationContext, message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.airavata.xbaya.jython.lib.ServiceNotifiable#receivedFault(xsul.wsif.WSIFMessage)
+ */
+ @Override
+ public void receivedFault(WSIFMessage fault) {
+ // XXX If error occurs before invoking a service, create a fake
+ // invocation context.
+ if (this.invocationContext == null) {
+ this.invocationContext = new InvocationContextImpl(this.initiator, this.receiver);
+ }
+
+ String message = "Received a fault message from the service";
+ XmlObject header = null;
+ XmlObject body;
+ try {
+ body = XmlObject.Factory.parse(fault.toString());
+ } catch (XmlException e) {
+ logger.warn("Failed to parse " + fault.toString(), e);
+ body = null; // Send notification anyway.
+ }
+ this.notifier.receivedFault(this.context, this.invocationContext, header, body, message);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/StandaloneServiceNotificationSender.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/StandaloneServiceNotificationSender.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/StandaloneServiceNotificationSender.java
new file mode 100644
index 0000000..8e9248d
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/StandaloneServiceNotificationSender.java
@@ -0,0 +1,95 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import java.net.URI;
+
+import org.apache.airavata.workflow.model.graph.Node;
+import org.apache.airavata.workflow.model.graph.Node.NodeExecutionState;
+import org.apache.airavata.workflow.model.wf.Workflow;
+import org.apache.airavata.xbaya.XBayaConstants;
+import org.apache.axis2.addressing.EndpointReference;
+
+import xsul.wsif.WSIFMessage;
+
+public class StandaloneServiceNotificationSender implements ServiceNotifiable {
+
+ private Workflow workflow;
+ private String serviceID;
+ private URI workflowID;
+
+ public StandaloneServiceNotificationSender(Workflow workflow, URI workflowID) {
+ this.workflow = workflow;
+ this.workflowID = workflowID;
+ }
+
+ @Override
+ public void setServiceID(String serviceID) {
+ this.serviceID = serviceID;
+ System.out.println(serviceID);
+
+ }
+
+ @Override
+ public EndpointReference getEventSink() {
+ return new EndpointReference(XBayaConstants.DEFAULT_BROKER_URL.toString());
+ }
+
+ @Override
+ public URI getWorkflowID() {
+ return this.workflowID;
+ }
+
+ @Override
+ public void invokingService(WSIFMessage inputs) {
+ getNode().setState(NodeExecutionState.EXECUTING);
+ }
+
+ @Override
+ public void serviceFinished(WSIFMessage outputs) {
+ getNode().setState(NodeExecutionState.FINISHED);
+
+ }
+
+ @Override
+ public void invocationFailed(String message, Throwable e) {
+ getNode().setState(NodeExecutionState.FAILED);
+
+ }
+
+ @Override
+ public void receivedFault(String message) {
+ getNode().setState(NodeExecutionState.FAILED);
+
+ }
+
+ @Override
+ public void receivedFault(WSIFMessage fault) {
+ getNode().setState(NodeExecutionState.FAILED);
+
+ }
+
+ private Node getNode() {
+ return this.workflow.getGraph().getNode(this.serviceID);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/WorkflowNotifiable.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/WorkflowNotifiable.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/WorkflowNotifiable.java
new file mode 100644
index 0000000..c44fa55
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/lib/WorkflowNotifiable.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.lib;
+
+import org.apache.axis2.addressing.EndpointReference;
+import org.python.core.PyObject;
+
+public interface WorkflowNotifiable {
+
+ /**
+ * @return The event sink EPR.
+ */
+ public abstract EndpointReference getEventSink();
+
+ /**
+ * @param args
+ * @param keywords
+ */
+ public abstract void workflowStarted(PyObject[] args, String[] keywords);
+
+ public abstract void workflowStarted(Object[] args, String[] keywords);
+
+ /**
+ * @param args
+ * @param keywords
+ */
+ public abstract void workflowFinished(Object[] args, String[] keywords);
+
+ public abstract void sendingPartialResults(Object[] args, String[] keywords);
+
+ /**
+ * @param args
+ * @param keywords
+ */
+ public abstract void workflowFinished(PyObject[] args, String[] keywords);
+
+ public abstract void workflowTerminated();
+
+ /**
+ * Sends a START_INCOMPLETED notification message.
+ *
+ * @param message
+ * The message to send
+ */
+ public abstract void workflowFailed(String message);
+
+ /**
+ * Sends a START_INCOMPLETED notification message.
+ *
+ * @param e
+ */
+ public abstract void workflowFailed(Throwable e);
+
+ /**
+ * Sends a START_INCOMPLETED notification message.
+ *
+ * @param message
+ * The message to send
+ * @param e
+ */
+ public abstract void workflowFailed(String message, Throwable e);
+
+ /**
+ * @param nodeID
+ * @return The ServiceNoficationSender created.
+ */
+ public abstract ServiceNotifiable createServiceNotificationSender(String nodeID);
+
+ public String getTopic();
+
+ public abstract void cleanup();
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonClassLoader.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonClassLoader.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonClassLoader.java
new file mode 100644
index 0000000..135e331
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonClassLoader.java
@@ -0,0 +1,423 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.runner;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.security.AllPermission;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.SecureClassLoader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.apache.airavata.common.utils.IOUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.airavata.xbaya.XBayaVersion;
+import org.apache.airavata.xbaya.jython.lib.NotificationSender;
+import org.python.util.PythonInterpreter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class loader loads jython related classes without counting on parent class loader. This is because jython
+ * related classes use a lot of static fields and cannot be used to invoke Jython scripts multiple times.
+ *
+ */
+public class JythonClassLoader extends SecureClassLoader {
+
+ private final static Logger logger = LoggerFactory.getLogger(JythonClassLoader.class);
+
+ private ClassLoader parent;
+
+ private Map<String, Class> classes = new HashMap<String, Class>();
+
+ private URL jythonURL;
+
+ private URL xbayaURL;
+
+ private JarFile jythonJarFile;
+
+ private JarFile xbayaJarFile;
+
+ private File tmpJarDirectory;
+
+ /**
+ * Constructs a JythonClassLoader.
+ *
+ * @param parent
+ * the parent class loader.
+ *
+ * This has to be explicitly passed because WebStart applications use user-level class loader. The
+ * default system loader cannot load classes in the downloaded jar files.
+ */
+ public JythonClassLoader(ClassLoader parent) {
+ super(parent);
+ this.parent = parent;
+
+ this.jythonURL = getBaseURL(PythonInterpreter.class);
+ this.xbayaURL = getBaseURL(XBayaVersion.class);
+ }
+
+ /**
+ * @return XBaya jar file.
+ */
+ public JarFile getXBayaJarFile() {
+ if (this.xbayaJarFile == null)
+ this.xbayaJarFile = maybeGetJarFile(this.xbayaURL);
+ return this.xbayaJarFile;
+ }
+
+ /**
+ * Cleans up temporary files.
+ */
+ public void cleanUp() {
+ this.jythonJarFile = null;
+ this.xbayaJarFile = null;
+ if (this.tmpJarDirectory != null) {
+ try {
+ IOUtil.deleteDirectory(this.tmpJarDirectory);
+ } catch (RuntimeException e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * @see java.lang.ClassLoader#loadClass(java.lang.String)
+ */
+ @Override
+ public Class<?> loadClass(String className) throws ClassNotFoundException {
+ return (loadClass(className, false));
+ }
+
+ /**
+ * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+ */
+ @Override
+ public synchronized Class<?> loadClass(String name, boolean resolveIt) throws ClassNotFoundException {
+
+ Class klass = null;
+ try {
+ klass = findClass(name);
+ } catch (ClassNotFoundException e) {
+ try {
+ klass = super.loadClass(name, false);
+ } catch (ClassNotFoundException e2) {
+ klass = this.parent.loadClass(name);
+ logger.debug("found from parent, klass: " + klass);
+ }
+ }
+
+ if (resolveIt) {
+ resolveClass(klass);
+ }
+
+ // logger.exiting(klass);
+ return klass;
+ }
+
+ @Override
+ protected Class<?> findClass(final String name) throws ClassNotFoundException {
+
+ // find jar location first
+ if (this.jythonJarFile == null)
+ this.jythonJarFile = maybeGetJarFile(this.jythonURL);
+ if (this.jythonJarFile == null)
+ this.xbayaJarFile = maybeGetJarFile(this.xbayaURL);
+
+ Class klass;
+
+ // Check if the class has been loaded by this class loader.
+ klass = this.classes.get(name);
+ if (klass != null) {
+ return klass;
+ }
+
+ // If the class is python, load separatly. NotificationSender also uses
+ // PyObject, so it has to be read from this class loader.
+ // JythonOneTimeRunner also needs to be loaded separatly.
+ if (name.startsWith("org.python.")) {
+ klass = findClassFromURL(name, this.jythonURL, this.jythonJarFile);
+ } else if (name.startsWith(NotificationSender.class.getPackage().getName())
+ || name.startsWith(JythonOneTimeRunnerImpl.class.getName())) {
+ klass = findClassFromURL(name, this.xbayaURL, this.xbayaJarFile);
+ }
+
+ if (klass != null) {
+ this.classes.put(name, klass);
+ return klass;
+ } else {
+ throw new ClassNotFoundException();
+ }
+ }
+
+ /**
+ * @see java.security.SecureClassLoader#getPermissions(java.security.CodeSource)
+ */
+ @Override
+ protected PermissionCollection getPermissions(CodeSource codesource) {
+ // Grant all perission. This could be avoided if code signers were
+ // extracted correctly.
+ Permissions permissions = new Permissions();
+ AllPermission permission = new AllPermission();
+ permissions.add(permission);
+ return permissions;
+ }
+
+ private URL getBaseURL(Class klass) {
+ String path = klass.getName().replace('.', '/').concat(".class"); // /d/e/f.class
+ URL classURL = this.parent.getResource(path);
+
+ String jarURLString;
+ if ("jar".equals(classURL.getProtocol())) {
+ // classURL = jar:file/a/b/c.jar!/d/e/f.class
+ // or jar:http://example.org/a/b/c.jar!/d/e/f.class
+ String file = classURL.getFile();
+ // file = file:/a/b/c.jar!d/e/f.class
+ // or http://example.org/a/b/c.jar!d/e/f.class
+ logger.debug("file: " + file);
+ jarURLString = file.substring(0, file.lastIndexOf('!'));
+ // jarURLString = file:/a/b/c.jar
+ // or http://example.org/a/b/c.jar
+ } else {
+ // file:/a/b/c/d/e/f.class
+ String file = classURL.getFile(); // /a/b/c/d/e/f.class
+ int index = file.lastIndexOf(path);
+ jarURLString = "file:" + file.substring(0, index); // /a/b/c/
+ }
+ try {
+ URL jarURL = new URL(jarURLString);
+ return jarURL;
+ } catch (MalformedURLException e) {
+ throw new WorkflowRuntimeException(e);
+ }
+ }
+
+ private JarFile maybeGetJarFile(URL url) {
+ String path;
+ try {
+ path = URLDecoder.decode(url.getPath(), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new WorkflowRuntimeException(e);
+ }
+ logger.debug("path: " + path);
+ if (path.endsWith("/")) {
+ // url = file:/a/b/c/
+ // It's a local directory
+ return null;
+ } else if ("file".equals(url.getProtocol())) {
+ // url = file:/a/b/c.jar
+ // Jar file
+ try {
+ JarFile jarFile = new JarFile(path);
+ return jarFile;
+ } catch (IOException e) {
+ throw new WorkflowRuntimeException(e);
+ }
+ } else {
+ // url = http://example.com/a/b/c.jar
+ // A Jar file
+ try {
+ if (this.tmpJarDirectory == null) {
+ Date date = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HHmmss-S");
+ String time = format.format(date);
+ String fileName = ".xbaya-jars-" + time;
+ String tmpdir = System.getProperty("java.io.tmpdir");
+ this.tmpJarDirectory = new File(tmpdir, fileName);
+ this.tmpJarDirectory.mkdir();
+ }
+
+ int i = path.lastIndexOf('/');
+ File file = new File(this.tmpJarDirectory, path.substring(i + 1));
+ logger.debug("file: " + file);
+ InputStream stream = url.openStream();
+ IOUtil.writeToFile(stream, file);
+ JarFile jarFile = new JarFile(file);
+ return jarFile;
+ } catch (IOException e) {
+ throw new WorkflowRuntimeException(e);
+ }
+ }
+ }
+
+ private Class findClassFromURL(String name, URL url, JarFile jarFile) throws ClassNotFoundException {
+ // logger.entering(new Object[] { name, url, jarFile });
+
+ String classPath = name.replace('.', '/').concat(".class");
+ // logger.info("classPath: " + classPath);
+
+ try {
+ byte[] classBytes;
+ CodeSource codeSource = null;
+ if (jarFile == null) {
+ // It's a local directory
+ String dirPath = URLDecoder.decode(url.getPath(), "UTF-8");
+ File classFile = new File(dirPath, classPath);
+ classBytes = IOUtil.readToByteArray(classFile);
+
+ } else {
+ // A Jar file
+ JarEntry jarEntry = jarFile.getJarEntry(classPath);
+ CodeSigner[] codeSigners = jarEntry.getCodeSigners();
+ // logger.info("codeSigners: " + codeSigners);
+ if (codeSigners != null) {
+ // Somehow it's null.
+ for (CodeSigner signer : codeSigners) {
+ logger.debug("signer: " + signer);
+ }
+ }
+ codeSource = new CodeSource(this.xbayaURL, codeSigners);
+ InputStream classInputStream = jarFile.getInputStream(jarEntry);
+ classBytes = IOUtil.readToByteArray(classInputStream);
+ }
+
+ Class<?> klass = defineClass(name, classBytes, 0, classBytes.length, codeSource);
+ this.classes.put(name, klass);
+ return klass;
+ } catch (IOException e) {
+ logger.error(e.getMessage(), e);
+ throw new ClassNotFoundException();
+ }
+ }
+
+ /**
+ * @see java.lang.ClassLoader#clearAssertionStatus()
+ */
+ @Override
+ public synchronized void clearAssertionStatus() {
+ super.clearAssertionStatus();
+ }
+
+ /**
+ * @see java.lang.ClassLoader#definePackage(java.lang.String, java.lang.String, java.lang.String, java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String, java.net.URL)
+ */
+ @Override
+ protected Package definePackage(String name, String specTitle, String specVersion, String specVendor,
+ String implTitle, String implVersion, String implVendor, URL sealBase) throws IllegalArgumentException {
+ return super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor,
+ sealBase);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#findLibrary(java.lang.String)
+ */
+ @Override
+ protected String findLibrary(String libname) {
+ return super.findLibrary(libname);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#findResource(java.lang.String)
+ */
+ @Override
+ protected URL findResource(String name) {
+ return super.findResource(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#findResources(java.lang.String)
+ */
+ @Override
+ protected Enumeration<URL> findResources(String name) throws IOException {
+ return super.findResources(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#getPackage(java.lang.String)
+ */
+ @Override
+ protected Package getPackage(String name) {
+ return super.getPackage(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#getPackages()
+ */
+ @Override
+ protected Package[] getPackages() {
+ return super.getPackages();
+ }
+
+ /**
+ * @see java.lang.ClassLoader#getResource(java.lang.String)
+ */
+ @Override
+ public URL getResource(String name) {
+ return super.getResource(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
+ */
+ @Override
+ public InputStream getResourceAsStream(String name) {
+ return super.getResourceAsStream(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#getResources(java.lang.String)
+ */
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ return super.getResources(name);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#setClassAssertionStatus(java.lang.String, boolean)
+ */
+ @Override
+ public synchronized void setClassAssertionStatus(String className, boolean enabled) {
+ super.setClassAssertionStatus(className, enabled);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#setDefaultAssertionStatus(boolean)
+ */
+ @Override
+ public synchronized void setDefaultAssertionStatus(boolean enabled) {
+ super.setDefaultAssertionStatus(enabled);
+ }
+
+ /**
+ * @see java.lang.ClassLoader#setPackageAssertionStatus(java.lang.String, boolean)
+ */
+ @Override
+ public synchronized void setPackageAssertionStatus(String packageName, boolean enabled) {
+ super.setPackageAssertionStatus(packageName, enabled);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunner.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunner.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunner.java
new file mode 100644
index 0000000..2ebd2ff
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunner.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.runner;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+
+public interface JythonOneTimeRunner {
+
+ /**
+ * @param script
+ * @param arguments
+ * @throws WorkflowException
+ */
+ public void run(String script, String[] arguments) throws WorkflowException;
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunnerImpl.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunnerImpl.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunnerImpl.java
new file mode 100644
index 0000000..6a4c532
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonOneTimeRunnerImpl.java
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.runner;
+
+import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.jar.JarFile;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JythonOneTimeRunnerImpl implements JythonOneTimeRunner {
+
+ private static final Logger logger = LoggerFactory.getLogger(JythonOneTimeRunnerImpl.class);
+
+ /**
+ * @throws WorkflowException
+ * @see org.apache.airavata.xbaya.jython.runner.JythonOneTimeRunner#run(java.lang.String, java.lang.String[])
+ */
+ public void run(final String script, final String[] arguments) throws WorkflowException {
+
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() {
+ ClassLoader loader = this.getClass().getClassLoader();
+
+ PySystemState.initialize(System.getProperties(), null, arguments, loader);
+
+ if (loader instanceof JythonClassLoader) {
+ logger.debug("jythonClassLoader");
+ JythonClassLoader jythonLoader = (JythonClassLoader) loader;
+
+ JarFile xbayaJarFile = jythonLoader.getXBayaJarFile();
+ if (xbayaJarFile != null) {
+ String jarPath = xbayaJarFile.getName();
+ logger.debug("jarPath: " + jarPath);
+ // String jarDir = jarPath.substring(0,
+ // jarPath.lastIndexOf());
+ File jarFile = new File(jarPath);
+ String jarDir = jarFile.getParent();
+ logger.debug("jarDir: " + jarDir);
+
+ // This is for the Jython interpreter to
+ // solve import statements.
+ PySystemState.add_extdir(jarDir);
+ }
+ }
+
+ PythonInterpreter interpreter = new PythonInterpreter();
+ interpreter.exec(script);
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ logger.error(e.getMessage(), e);
+ throw new WorkflowException(e.getCause());
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c47eec8/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonRunner.java
----------------------------------------------------------------------
diff --git a/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonRunner.java b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonRunner.java
new file mode 100644
index 0000000..7fe1f93
--- /dev/null
+++ b/modules/xbaya-gui/src/main/java/org/apache/airavata/xbaya/jython/runner/JythonRunner.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.xbaya.jython.runner;
+
+import java.util.List;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.airavata.xbaya.ui.utils.ErrorMessages;
+
+public class JythonRunner {
+
+ private JythonClassLoader loader;
+
+ /**
+ *
+ * Constructs a JythonRunner.
+ *
+ */
+ public JythonRunner() {
+ this.loader = new JythonClassLoader(this.getClass().getClassLoader());
+ }
+
+ /**
+ * @param script
+ * @param arguments
+ * @throws WorkflowException
+ */
+ public void run(String script, List<String> arguments) throws WorkflowException {
+ run(script, arguments.toArray(new String[arguments.size()]));
+ }
+
+ /**
+ * @param script
+ * @param arguments
+ * @throws WorkflowException
+ */
+ public void run(final String script, final String[] arguments) throws WorkflowException {
+ try {
+ Class<?> runnerClass = this.loader.loadClass(JythonOneTimeRunnerImpl.class.getName(), true);
+ JythonOneTimeRunner runner = (JythonOneTimeRunner) runnerClass.newInstance();
+ runner.run(script, arguments);
+
+ } catch (ClassNotFoundException e) {
+ throw new WorkflowRuntimeException(ErrorMessages.UNEXPECTED_ERROR, e);
+ } catch (InstantiationException e) {
+ throw new WorkflowRuntimeException(ErrorMessages.UNEXPECTED_ERROR, e);
+ } catch (IllegalAccessException e) {
+ throw new WorkflowRuntimeException(ErrorMessages.UNEXPECTED_ERROR, e);
+ } finally {
+ loader.cleanUp();
+ }
+ }
+}
\ No newline at end of file