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