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 2012/11/19 18:05:12 UTC

svn commit: r1411310 - in /airavata/trunk/modules/ws-messenger/message-monitor: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/airavata/ src/main/java/org/apache/airavata/ws/ src/main/java/org/apa...

Author: samindaw
Date: Mon Nov 19 17:05:10 2012
New Revision: 1411310

URL: http://svn.apache.org/viewvc?rev=1411310&view=rev
Log:
adding monitoring module

Added:
    airavata/trunk/modules/ws-messenger/message-monitor/
    airavata/trunk/modules/ws-messenger/message-monitor/pom.xml
    airavata/trunk/modules/ws-messenger/message-monitor/src/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/EventFilter.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/Monitor.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorConfiguration.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEvent.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventData.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventListener.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorException.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorUtil.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/WsmgClient.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/Event.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventListener.java
    airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventProducer.java

Added: airavata/trunk/modules/ws-messenger/message-monitor/pom.xml
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/pom.xml?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/pom.xml (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/pom.xml Mon Nov 19 17:05:10 2012
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <parent>
+        <groupId>org.apache.airavata</groupId>
+        <artifactId>airavata-ws-messenger</artifactId>
+        <version>0.6-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>airavata-message-monitor</artifactId>
+    <name>Airavata WS Monitor</name>
+    <url>http://airavata.apache.org/</url>
+    <packaging>jar</packaging>
+
+
+    <dependencies>
+		<dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-workflow-model-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-messenger-commons</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-registry-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-common-utils</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>edu.berkeley</groupId>
+            <artifactId>yfilter</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>wsdl4j</groupId>
+            <artifactId>wsdl4j</artifactId>
+            <version>1.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-transport-http</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-transport-local</artifactId>
+        </dependency>
+
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>airavata-messenger-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    </properties>
+</project>

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/EventFilter.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/EventFilter.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/EventFilter.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/EventFilter.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.ws.monitor;
+
+public interface EventFilter {
+
+    public boolean isAcceptable(MonitorEvent event);
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/Monitor.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/Monitor.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/Monitor.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/Monitor.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,246 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.ws.monitor.event.Event;
+import org.apache.airavata.ws.monitor.event.EventProducer;
+import org.apache.airavata.ws.monitor.event.Event.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+public class Monitor extends EventProducer {
+
+    protected static final Logger logger = LoggerFactory.getLogger(Monitor.class);
+
+    protected MonitorConfiguration configuration;
+
+    protected static final String DEFAULT_MODEL_KEY = "_DEFAULT_MODEL_KEY";
+
+    protected Map<String, MonitorEventData> eventDataMap = new HashMap<String, MonitorEventData>();
+
+    protected WsmgClient wsmgClient;
+
+    protected boolean print;
+
+    protected long timeout = 20000L;
+
+    protected boolean status = false;
+    
+    /**
+     * Constructs a Monitor.
+     * 
+     * @param configuration
+     */
+    public Monitor(MonitorConfiguration configuration) {
+        this.configuration = configuration;
+        // The first one is special and it is for the main event panel display
+        // and
+        // it does not have and filters
+        this.eventDataMap.put(DEFAULT_MODEL_KEY, new MonitorEventData());
+
+
+    }
+
+    /**
+     * @return The configuration
+     */
+    public MonitorConfiguration getConfiguration() {
+        return this.configuration;
+    }
+
+    /**
+     * @return The event data;
+     */
+    public MonitorEventData getEventData() {
+        // send the first one cos that is the default one
+        return this.eventDataMap.get(DEFAULT_MODEL_KEY);
+    }
+
+    /**
+     * @return The event data;
+     */
+    public MonitorEventData getEventData(String nodeID) {
+        // send the first one cos that is the default one
+        return this.eventDataMap.get(nodeID);
+    }
+
+    /**
+     * @throws MonitorException
+     */
+    public synchronized void start() throws MonitorException {
+        // Stop the previous monitoring if any.
+        asynchronousStop();
+
+        subscribe();
+
+        if (null != this.configuration.getInteractiveNodeIDs()) {
+            List<String> interactiveNodeIDs = this.configuration.getInteractiveNodeIDs();
+            // now add models for this as well
+            for (String string : interactiveNodeIDs) {
+
+                final String nodeID = string;
+                // for each wsnode there is one data model which
+                this.eventDataMap.put(nodeID, new MonitorEventData(new EventFilter() {
+                    /**
+                     * @see org.apache.airavata.ws.monitor.EventFilter#isAcceptable(org.apache.airavata.ws.monitor.MonitorEvent)
+                     */
+                    public boolean isAcceptable(MonitorEvent event) {
+                        return event != null && event.getNodeID() != null && event.getNodeID().equals(nodeID);
+                    }
+                }));
+            }
+
+        }
+    }
+    
+    public void startMonitoring(){
+    	final Monitor m=this;
+    	new Thread(){
+    		@Override
+    		public void run() {
+    			try {
+					m.start();
+				} catch (MonitorException e) {
+					e.printStackTrace();
+				}
+    		}
+    	}.start();
+    }
+
+    /**
+     * Stops monitoring.
+     */
+    public synchronized void asynchronousStop() {
+        if (this.wsmgClient != null) {
+            // To make thread safe.
+            final WsmgClient client = this.wsmgClient;
+            this.wsmgClient = null;
+
+            // Users don't need to know the end of unsubscription.
+            new Thread() {
+                @Override
+                public void run() {
+                    try {
+                        unsubscribe(client);
+                    } catch (WorkflowException e) {
+                        // Ignore the error in unsubscription.
+                        logger.error(e.getMessage(), e);
+                    }
+                }
+            }.start();
+        }
+    }
+
+    /**
+     * Stops monitoring without using a thread.
+     * 
+     * @throws MonitorException
+     */
+    public synchronized void stop() throws MonitorException {
+        if (this.wsmgClient != null) {
+            unsubscribe(this.wsmgClient);
+            this.wsmgClient = null;
+        }
+    }
+
+    /**
+     * Resets the graph and clear the monitoring table. Remove all the extra tablemodels available
+     */
+    public void reset() {
+        Set<String> keys = this.eventDataMap.keySet();
+        LinkedList<String> keysToBeRemoved = new LinkedList<String>();
+        // Remove everthing leaving only the last one
+        for (String key : keys) {
+            MonitorEventData monitorEventData = this.eventDataMap.get(key);
+            monitorEventData.removeAllEvents();
+            if (!key.equals(DEFAULT_MODEL_KEY)) {
+                keysToBeRemoved.add(key);
+            }
+        }
+        for (String key : keysToBeRemoved) {
+            this.eventDataMap.remove(key);
+        }
+
+    }
+
+    /**
+     * @param event
+     */
+    public synchronized void handleNotification(XmlElement event) {
+        Set<String> keys = this.eventDataMap.keySet();
+        // Remove everthing leaving only the last one
+        if(print){
+            System.out.println(XMLUtil.xmlElementToString(event));
+        }
+        for (String key : keys) {
+            this.eventDataMap.get(key).addEvent(event);
+        }
+    }
+
+    private void subscribe() throws MonitorException {
+        this.wsmgClient = new WsmgClient(this);
+        this.wsmgClient.setTimeout(this.getTimeout());
+        //Users can set the timeout and interval for the subscription using wsmg setter methods, here we use the default values
+        this.wsmgClient.subscribe();
+        this.status = true;
+
+        // Enable/disable some menu items and show the monitor panel.
+        sendSafeEvent(new Event(Type.MONITOR_STARTED));
+    }
+
+    private void unsubscribe(WsmgClient client) throws MonitorException {
+        // Enable/disable some menu items.
+        sendSafeEvent(new Event(Type.MONITOR_STOPED));
+
+        client.unsubscribe();
+        this.status = false;
+    }
+
+    public void setPrint(boolean print) {
+        this.print = print;
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public boolean isStatus() {
+        return status;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorConfiguration.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorConfiguration.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorConfiguration.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorConfiguration.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,191 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.airavata.ws.monitor.event.Event;
+import org.apache.airavata.ws.monitor.event.EventProducer;
+import org.apache.airavata.ws.monitor.event.Event.Type;
+import org.apache.airavata.common.utils.StringUtil;
+
+public class MonitorConfiguration extends EventProducer implements Cloneable{
+
+    // private static final Logger logger = LoggerFactory.getLogger();
+
+    private URI brokerURL;
+
+    private String topic;
+
+    private boolean pullMode;
+
+    private URI messageBoxURL;
+
+    private List<String> interactiveNodeIDs = null;
+
+    /**
+     * Constructs a NotificationConfiguration.
+     * 
+     * @param brokerURL
+     * @param topic
+     * @param pullMode
+     * @param messageBoxURL
+     */
+    public MonitorConfiguration(URI brokerURL, String topic, boolean pullMode, URI messageBoxURL) {
+        set(brokerURL, topic, pullMode, messageBoxURL);
+    }
+
+    /**
+     * @param brokerURL
+     * @param topic
+     * @param pullMode
+     * @param messageBoxURL
+     */
+    public void set(URI brokerURL, String topic, boolean pullMode, URI messageBoxURL) {
+        this.brokerURL = brokerURL;
+        this.topic = topic;
+        this.pullMode = pullMode;
+        this.messageBoxURL = messageBoxURL;
+        sendSafeEvent(new Event(Type.MONITOR_CONFIGURATION_CHANGED));
+    }
+
+    /**
+     * @param brokerURL
+     *            The brokerLocation to set.
+     */
+    public void setBrokerURL(URI brokerURL) {
+        this.brokerURL = brokerURL;
+        sendSafeEvent(new Event(Type.MONITOR_CONFIGURATION_CHANGED));
+    }
+
+    /**
+     * Returns the URL of the notification broker.
+     * 
+     * @return The URL of the notification broker
+     */
+    public URI getBrokerURL() {
+        return this.brokerURL;
+    }
+
+    /**
+     * @param topic
+     *            The topic to set
+     */
+    public void setTopic(String topic) {
+        this.topic = StringUtil.trimAndNullify(topic);
+        sendSafeEvent(new Event(Type.MONITOR_CONFIGURATION_CHANGED));
+    }
+
+    /**
+     * @return The userId.
+     */
+    public String getTopic() {
+        return this.topic;
+    }
+
+    /**
+     * Returns the messageBoxUrl.
+     * 
+     * @return The messageBoxUrl
+     */
+    public URI getMessageBoxURL() {
+        return this.messageBoxURL;
+    }
+
+    /**
+     * Sets messageBoxUrl.
+     * 
+     * @param messageBoxURL
+     *            The messageBoxUrl to set.
+     */
+    public void setMessageBoxURL(URI messageBoxURL) {
+        this.messageBoxURL = messageBoxURL;
+        sendSafeEvent(new Event(Type.MONITOR_CONFIGURATION_CHANGED));
+    }
+
+    /**
+     * Returns the pullMode.
+     * 
+     * @return The pullMode
+     */
+    public boolean isPullMode() {
+        return this.pullMode;
+    }
+
+    /**
+     * Sets pullMode.
+     * 
+     * @param pullMode
+     *            The pullMode to set.
+     */
+    public void setPullMode(boolean pullMode) {
+        this.pullMode = pullMode;
+        sendSafeEvent(new Event(Type.MONITOR_CONFIGURATION_CHANGED));
+    }
+
+    /**
+     * @return true if the configuration is valid; false otherwise.
+     */
+    public boolean isValid() {
+        if (this.brokerURL == null) {
+            return false;
+        }
+        if (this.topic == null || this.topic.length() == 0) {
+            return false;
+        }
+        if (this.pullMode == true) {
+            if (this.messageBoxURL == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public MonitorConfiguration clone() {
+        return new MonitorConfiguration(this.brokerURL, this.topic, this.pullMode, this.messageBoxURL);
+    }
+
+    /**
+     * Returns the interactiveNodeIDs.
+     * 
+     * @return The interactiveNodeIDs
+     */
+    public List<String> getInteractiveNodeIDs() {
+        return this.interactiveNodeIDs;
+    }
+
+    /**
+     * Sets interactiveNodeIDs.
+     * 
+     * @param interactiveNodeIDs
+     *            The interactiveNodeIDs to set.
+     */
+    public void setInteractiveNodeIDs(List<String> interactiveNodeIDs) {
+        this.interactiveNodeIDs = interactiveNodeIDs;
+    }
+
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEvent.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEvent.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEvent.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEvent.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,174 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.net.URI;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.airavata.ws.monitor.MonitorUtil.EventType;
+import org.xmlpull.infoset.XmlElement;
+
+public class MonitorEvent {
+
+    private String timeText;
+    
+    private Date timestamp;
+
+    private String idText;
+
+    private String statusText;
+
+    private String message;
+
+    private XmlElement event;
+
+    private EventType type;
+
+    private URI workflowID;
+
+    private String nodeID;
+
+    private String experimentID;
+
+    /**
+     * Constructs a MonitorEvent.
+     * 
+     * @param event
+     */
+    public MonitorEvent(XmlElement event) {
+        this.event = event;
+        parse();
+    }
+
+    /**
+     * Returns the event.
+     * 
+     * @return The event
+     */
+    public XmlElement getEvent() {
+        return this.event;
+    }
+
+    /**
+     * Returns the idText.
+     * 
+     * @return The idText
+     */
+    public String getIDText() {
+        return this.idText;
+    }
+
+    /**
+     * Returns the message.
+     * 
+     * @return The message
+     */
+    public String getMessage() {
+        return this.message;
+    }
+
+    /**
+     * Returns the statusText.
+     * 
+     * @return The statusText
+     */
+    public String getStatusText() {
+        return this.statusText;
+    }
+
+    /**
+     * Returns the timeText.
+     * 
+     * @return The timeText
+     */
+    public String getTimeText() {
+        return this.timeText;
+    }
+
+    /**
+     * Returns the type.
+     * 
+     * @return The type
+     */
+    public EventType getType() {
+        return this.type;
+    }
+
+    /**
+     * Returns the workflowID.
+     * 
+     * @return The workflowID
+     */
+    public URI getWorkflowID() {
+        return this.workflowID;
+    }
+
+    /**
+     * Returns the nodeID.
+     * 
+     * @return The nodeID
+     */
+    public String getNodeID() {
+        return this.nodeID;
+    }
+
+    private void parse() {
+        this.type = MonitorUtil.getType(this.event);
+        this.workflowID = MonitorUtil.getWorkflowID(this.event);
+        this.nodeID = MonitorUtil.getNodeID(this.event);
+        this.experimentID = MonitorUtil.getExperiementID(this.event);
+        timestamp = MonitorUtil.getTimestamp(this.event);
+
+        if (timestamp != null) {
+            SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.S MM/dd/yy ");
+            this.timeText = format.format(timestamp);
+        } else {
+            this.timeText = "";
+        }
+
+        this.idText = this.nodeID;
+
+        this.statusText = MonitorUtil.getStatus(this.event);
+
+        this.message = MonitorUtil.getMessage(this.event);
+        if (this.type == MonitorUtil.EventType.PUBLISH_URL) {
+            String location = MonitorUtil.getLocation(this.event);
+            // should be looked into
+            // String url = PREFIX + location + SUFFIX;
+            String url = location;
+            this.message = "<html>" + this.message + ": " + "<a href=\"" + url + "\">" + url + " </a></html>";
+        }
+    }
+
+	public Date getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(Date timestamp) {
+		this.timestamp = timestamp;
+	}
+
+    public String getExperimentID() {
+        return experimentID;
+    }
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventData.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventData.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventData.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventData.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,451 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.BoundedRangeModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableModel;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+public class MonitorEventData implements TableModel, BoundedRangeModel {
+
+    /**
+     * Column
+     */
+    public static enum Column {
+        /**
+         * TIME
+         */
+        TIME("Time"),
+        /**
+         * ID
+         */
+        ID("Component"),
+        /**
+         * STATUS
+         */
+        STATUS("Status"),
+        /**
+         * MESSAGE
+         */
+        MESSAGE("Message");
+
+        private String name;
+
+        private Column(String name) {
+            this.name = name;
+        }
+
+        /**
+         * @return The name.
+         */
+        public String getName() {
+            return this.name;
+        }
+    }
+
+    private static final Logger logger = LoggerFactory.getLogger(MonitorEventData.class);
+
+    private List<TableModelListener> tableModelListeners;
+
+    private List<ChangeListener> sliderModelListeners;
+
+    private List<MonitorEvent> events;
+
+    private int sliderValue;
+
+    private boolean sliderAdjusting;
+
+    private ChangeEvent tableModelChangeEvent;
+
+    private EventFilter filter;
+
+    private List<MonitorEventListener> monitorEventListerners;
+
+    /**
+     * 
+     * Constructs a MonitorEventData.
+     * 
+     */
+    public MonitorEventData() {
+        this(null);
+    }
+
+    /**
+     * Constructs a NotificationTableModel.
+     */
+    public MonitorEventData(EventFilter filter) {
+        this.filter = filter;
+        this.tableModelListeners = new LinkedList<TableModelListener>();
+        this.sliderModelListeners = new LinkedList<ChangeListener>();
+        this.tableModelChangeEvent = new ChangeEvent(this); // We only need one.
+        this.events = new ArrayList<MonitorEvent>();
+    }
+
+    /**
+     * @param message
+     */
+    public void addEvent(XmlElement message) {
+        MonitorEvent event = new MonitorEvent(message);
+        // no need the check for not null because second clause is evaluated only if
+        // not null
+        if (this.filter == null || this.filter.isAcceptable(event)) {
+            boolean sliderMax = (this.sliderValue == this.events.size());
+
+            this.events.add(event);
+
+            if (sliderMax) {
+                // Move the slider to the max
+                this.sliderValue = this.events.size();
+
+                // The new event shows up on the table only when the slider is
+                // max.
+                TableModelEvent tableEvent = new TableModelEvent(this, this.sliderValue - 1, this.sliderValue,
+                        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
+                fireTableChanged(tableEvent);
+            }
+
+            // The muxmum of the slider changed regardless whether we move the
+            // slider or not.
+            fireSliderChanged();
+            for (MonitorEventListener listener : getMonitorEventListerners()) {
+				try {
+					listener.notify(this, event);
+				} catch (Exception e) {
+					//just in case
+					e.printStackTrace();
+				}
+			}
+
+        }
+
+    }
+
+    /**
+     * @return All events.
+     */
+    public List<MonitorEvent> getEvents() {
+        return this.events;
+    }
+
+    /**
+     * Returns a notification at a specified row.
+     * 
+     * @param index
+     *            The specified row.
+     * @return The notification at the specified row
+     */
+    public MonitorEvent getEvent(int index) {
+        return this.events.get(index);
+    }
+
+    /**
+     * @return The number of events.
+     */
+    public int getEventSize() {
+        return this.events.size();
+    }
+
+    /**
+     * Clears the notifications.
+     */
+    public void removeAllEvents() {
+        int size = this.events.size();
+        this.events.clear();
+
+        this.sliderValue = 0;
+
+        TableModelEvent event = new TableModelEvent(this, 0, Math.max(0, size - 1), TableModelEvent.ALL_COLUMNS,
+                TableModelEvent.DELETE);
+        fireTableChanged(event);
+
+        // The muxmum of the slider changed.
+        fireSliderChanged();
+    }
+
+    // methods implementing TableModel interface.
+
+    /**
+     * @see javax.swing.table.TableModel#getRowCount()
+     */
+    public int getRowCount() {
+        // Only show the events up to the slider value.
+        return this.sliderValue;
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#getColumnCount()
+     */
+    public int getColumnCount() {
+        return Column.values().length;
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#getColumnName(int)
+     */
+    public String getColumnName(int columnIndex) {
+        Column[] columns = Column.values();
+        if (columnIndex < 0 || columnIndex >= columns.length) {
+            // Should not happen.
+            throw new IllegalArgumentException("columnIndex has be be between 0 to " + columns.length);
+        }
+        return columns[columnIndex].getName();
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#getColumnClass(int)
+     */
+    public Class<?> getColumnClass(int columnIndex) {
+        return String.class;
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#isCellEditable(int, int)
+     */
+    public boolean isCellEditable(int rowIndex, int columnIndex) {
+        return false;
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#getValueAt(int, int)
+     */
+    public Object getValueAt(int rowIndex, int columnIndex) {
+        String value;
+        try {
+            MonitorEvent event = this.events.get(rowIndex);
+            value = getTextAt(event, columnIndex);
+        } catch (RuntimeException e) {
+            // This should not happen, but if it happens it blocks the UI.
+            // That's why catching it.
+            logger.error(e.getMessage(), e);
+            value = "Error";
+        }
+        return value;
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
+     */
+    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#addTableModelListener(javax.swing.event.TableModelListener)
+     */
+    public void addTableModelListener(TableModelListener listener) {
+        this.tableModelListeners.add(listener);
+    }
+
+    /**
+     * @see javax.swing.table.TableModel#removeTableModelListener(javax.swing.event.TableModelListener)
+     */
+    public void removeTableModelListener(TableModelListener listener) {
+        this.tableModelListeners.remove(listener);
+    }
+
+    // methods implementing BoundedRangeModel interface.
+
+    /**
+     * @see javax.swing.BoundedRangeModel#getExtent()
+     */
+    public int getExtent() {
+        return 0;
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setExtent(int)
+     */
+    public void setExtent(int newExtent) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#getMaximum()
+     */
+    public int getMaximum() {
+        return getEventSize();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setMaximum(int)
+     */
+    public void setMaximum(int newMaximum) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#getMinimum()
+     */
+    public int getMinimum() {
+        return 0;
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setMinimum(int)
+     */
+    public void setMinimum(int newMinimum) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#getValue()
+     */
+    public int getValue() {
+        return this.sliderValue;
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setValue(int)
+     */
+    public void setValue(int newValue) {
+        if (this.sliderValue == newValue) {
+            return;
+        }
+
+        // Correct the value to be withing the range.
+        if (newValue < 0) {
+            newValue = 0;
+        }
+        if (newValue > this.events.size()) {
+            newValue = this.events.size();
+        }
+
+        int oldRowCount = this.sliderValue;
+        this.sliderValue = newValue;
+
+        TableModelEvent event;
+        if (oldRowCount < this.sliderValue) {
+            event = new TableModelEvent(this, oldRowCount, this.sliderValue, TableModelEvent.ALL_COLUMNS,
+                    TableModelEvent.INSERT);
+        } else {
+            event = new TableModelEvent(this, this.sliderValue, oldRowCount, TableModelEvent.ALL_COLUMNS,
+                    TableModelEvent.DELETE);
+        }
+        fireTableChanged(event);
+        fireSliderChanged();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#getValueIsAdjusting()
+     */
+    public boolean getValueIsAdjusting() {
+        return this.sliderAdjusting;
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setValueIsAdjusting(boolean)
+     */
+    public void setValueIsAdjusting(boolean adjusting) {
+        this.sliderAdjusting = adjusting;
+        fireSliderChanged();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#setRangeProperties(int, int, int, int, boolean)
+     */
+    public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#addChangeListener(javax.swing.event.ChangeListener)
+     */
+    public void addChangeListener(ChangeListener listener) {
+        this.sliderModelListeners.add(listener);
+    }
+
+    /**
+     * @see javax.swing.BoundedRangeModel#removeChangeListener(javax.swing.event.ChangeListener)
+     */
+    public void removeChangeListener(ChangeListener listener) {
+        this.sliderModelListeners.remove(listener);
+    }
+
+    private String getTextAt(MonitorEvent event, int columnIndex) {
+        Column[] columns = Column.values();
+        if (columnIndex < 0 || columnIndex >= columns.length) {
+            // Should not happen.
+            throw new IllegalArgumentException("columnIndex has be be between 0 to " + columns.length);
+        }
+        Column column = columns[columnIndex];
+        String value;
+        switch (column) {
+        case TIME:
+            value = event.getTimeText();
+            break;
+        case ID:
+            value = event.getIDText();
+            break;
+        case STATUS:
+            value = event.getStatusText();
+            break;
+        case MESSAGE:
+            value = event.getMessage();
+            break;
+        default:
+            // Should not happen.
+            throw new IllegalArgumentException("columnIndex has be be between 0 to " + columns.length);
+        }
+        return value;
+    }
+
+    private void fireTableChanged(TableModelEvent event) {
+        for (TableModelListener listener : this.tableModelListeners) {
+            listener.tableChanged(event);
+        }
+    }
+
+    private void fireSliderChanged() {
+        for (ChangeListener listener : this.sliderModelListeners) {
+            listener.stateChanged(this.tableModelChangeEvent);
+        }
+    }
+	private List<MonitorEventListener> getMonitorEventListerners() {
+		if (monitorEventListerners==null){
+			monitorEventListerners=new ArrayList<MonitorEventListener>();
+		}
+		return monitorEventListerners;
+	}
+
+	public void registerEventListener(MonitorEventListener listener){
+		if (listener!=null) {
+			getMonitorEventListerners().add(listener);
+		}
+	}
+	
+	public void unregisterEventListener(MonitorEventListener listener){
+		if (getMonitorEventListerners().contains(listener)) {
+			getMonitorEventListerners().remove(listener);
+		}
+	}
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventListener.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventListener.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventListener.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorEventListener.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.ws.monitor;
+
+public interface MonitorEventListener {
+	public void notify(MonitorEventData eventData, MonitorEvent event);
+}

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorException.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorException.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorException.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorException.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,62 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+
+public class MonitorException extends WorkflowException {
+
+    /**
+     * Constructs a MonitorException.
+     */
+    public MonitorException() {
+        super();
+    }
+
+    /**
+     * Constructs a MonitorException.
+     * 
+     * @param message
+     */
+    public MonitorException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a MonitorException.
+     * 
+     * @param cause
+     */
+    public MonitorException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a MonitorException.
+     * 
+     * @param message
+     * @param cause
+     */
+    public MonitorException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorUtil.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorUtil.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorUtil.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/MonitorUtil.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,627 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+import org.xmlpull.infoset.XmlNamespace;
+
+import atomixmiser.DcDate;
+
+/**
+ * Manipulate XML Events
+ */
+public class MonitorUtil {
+
+    private static final Logger logger = LoggerFactory.getLogger(MonitorUtil.class);
+
+    /**
+     * Workflow tracking namespace
+     */
+    public static final XmlNamespace WOR_NS = XMLUtil.BUILDER.newNamespace("wor",
+            "http://airavata.apache.org/schemas/workflow_tracking_types");
+
+    /**
+     * XBaya events namespace
+     */
+    public static final XmlNamespace XBAYA_EVENTS_NS = XMLUtil.BUILDER.newNamespace("xbaya",
+            "http://www.extreme.indiana.edu/xgws/xbaya/ns/2006/");
+
+    /**
+     * gotResult
+     */
+    public static final String GOT_RESULT_EVENT_TAG = "receivedResult";
+
+    /**
+     * description
+     */
+    public static final String DESCRIPTION_TAG = "description";
+
+    /**
+     * timestamp
+     */
+    public static final String TIMESTAMP_TAG = "timestamp";
+
+    /**
+     * request
+     * 
+     * In invokingService
+     */
+    public static final String REQUEST = "request";
+
+    /**
+     * result
+     * 
+     * In sendingResult
+     */
+    public static final String RESULT = "result";
+
+    /**
+     * body
+     * 
+     * In sendingResult
+     */
+    public static final String BODY = "body";
+
+    /**
+     * experimentID
+     * In Notification Message
+     */
+    public static final String WORKFLOW_EXPERIMENT_ID = "experimentID";
+    /**
+     * workflowID
+     * 
+     * workflow instance ID.
+     */
+    private static final String WORKFLOW_ID_ATTRIBUTE = "workflowID";
+
+    /**
+     * serviceID
+     * 
+     * In workflowInitialized notification, this is the worklfow instance ID.
+     */
+    private static final String SERVICE_ID_ATTRIBUTE = "serviceID";
+
+    /**
+     * workflowNodeID
+     * 
+     * Node ID.
+     */
+    private static final String WORKFLOW_NODE_ID_ATTRIBUTE = "workflowNodeID";
+
+    /**
+     * receiver
+     * 
+     * Extract a node ID from here when a notification is sent by a workflow when the workflow is sending a message to a
+     * service.
+     */
+    private static final String RECEIVER_TAG = "receiver";
+
+    /**
+     * responder
+     * 
+     * Extract a node ID from here when a notification is sent by a workflow when the workflow is receiving a message
+     * from a service.
+     */
+    private static final String RESPONDER_TAG = "responder";
+
+    /**
+     * notificationSource
+     * 
+     * Extract a node ID from here when a service sends notification.
+     */
+    private static final String NOTIFICATION_SOURCE_TAG = "notificationSource";
+
+    // Followings are specific to some event types.
+
+    /**
+     * location
+     * 
+     * In publishURL
+     */
+    private static final String LOCATION_TAG = "location";
+
+    /**
+     * retryStatusCount
+     * 
+     * In computationDuration
+     */
+    private static final String RETRY_STATUS_COUNT_TAG = "retryStatusCount";
+
+    /**
+     * mappedResource
+     * 
+     * In resourceMapping
+     */
+    private static final String MAPPED_RESOURCE_TAG = "mappedResource";
+
+    /**
+     * dataProduct
+     * 
+     * In a couple of data-related notifications.
+     */
+    private static final String DATA_PRODUCT_TAG = "dataProduct";
+
+    /**
+     * durationInMillis
+     * 
+     * In computationDuration
+     */
+    @SuppressWarnings("unused")
+    private static final String DURATION_IN_MILLS_TAG = "durationInMillis";
+
+    /**
+     * Type of the notification event.
+     */
+    public enum EventType {
+        /**
+         * unknown
+         */
+        UNKNOWN("unknown"),
+
+        // Notification from a workflow
+
+        /**
+         * workflowInitialized
+         */
+        WORKFLOW_INITIALIZED("workflowInitialized"),
+
+        /**
+         * workflowInvoked
+         */
+        WORKFLOW_INVOKED("workflowInvoked"),
+
+        /**
+         * workflowTerminated
+         */
+        WORKFLOW_TERMINATED("workflowTerminated"),
+
+        /**
+         * invokingService
+         */
+        INVOKING_SERVICE("invokingService"),
+
+        /**
+         * invokingServiceSucceeded
+         */
+        INVOKING_SERVICE_SUCCEEDED("invokingServiceSucceeded"),
+
+        /**
+         * invokingServiceFailed
+         */
+        INVOKING_SERVICE_FAILED("invokingServiceFailed"),
+
+        /**
+         * receivedResult
+         */
+        RECEIVED_RESULT("receivedResult"),
+
+        /**
+         * receivedFault
+         */
+        RECEIVED_FAULT("receivedFault"),
+
+        // Notification from a service
+
+        /**
+         * serviceInvoked
+         */
+        SERVICE_INVOKED("serviceInvoked"),
+
+        /**
+         * sendingResult
+         */
+        SENDING_RESULT("sendingResult"),
+
+        /**
+         * sendingResponseFailed
+         */
+        SENDING_RESPONSE_FAILED("sendingResponseFailed"),
+
+        /**
+         * sendingFault
+         */
+        SENDING_FAULT("sendingFault"),
+
+        // Other types of notification from a service.
+        /**
+         * logInfo
+         */
+        LOG_INFO("logInfo"),
+
+        /**
+         * logException
+         */
+        LOG_EXCEPTION("logException"),
+
+        /**
+         * logWarning
+         */
+        LOG_WARNING("logWarning"),
+
+        /**
+         * logDebug
+         */
+        LOG_DEBUG("logDebug"),
+
+        /**
+         * dataConsumed
+         */
+        DATA_CONSUMED("dataConsumed"),
+
+        /**
+         * dataProduced
+         */
+        DATA_PRODUCED("dataProduced"),
+
+        /**
+         * dataReceiveDuration
+         */
+        DATA_RECEIVE_DURATION("dataReceiveDuration"),
+
+        /**
+         * applicationAudit
+         */
+        APPLICATION_AUDIT("applicationAudit"),
+
+        /**
+         * computationDuration
+         */
+        COMPUTATION_DURATION("computationDuration"),
+
+        /**
+         * publishURL
+         */
+        PUBLISH_URL("publishURL"),
+
+        /**
+         * resourceMapping
+         */
+        RESOURCE_MAPPING("resourceMapping");
+
+        String name;
+
+        EventType(String name) {
+            this.name = name;
+        }
+    }
+
+    /**
+     * @param event
+     * @return The type of the event.
+     */
+    public static EventType getType(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        XmlNamespace ns = event.getNamespace();
+        String name = event.getName();
+        if (XBAYA_EVENTS_NS.equals(ns)) {
+            if (GOT_RESULT_EVENT_TAG.equals(name)) {
+                return EventType.WORKFLOW_TERMINATED;
+            } else {
+                return EventType.UNKNOWN;
+            }
+        } else if (WOR_NS.equals(ns)) {
+            for (EventType type : EventType.values()) {
+                if (type.name.equals(name)) {
+                    return type;
+                }
+            }
+        }
+        return EventType.UNKNOWN;
+    }
+
+    /**
+     * @param event
+     * @return The timestamp.
+     */
+    public static Date getTimestamp(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        XmlElement timestampEl = event.element(WOR_NS, TIMESTAMP_TAG);
+        if (timestampEl == null)
+            return null;
+        String timestamp = timestampEl.requiredText();
+        DcDate date = DcDate.create(timestamp);
+        return new Date(date.getTimeInMillis());
+    }
+
+    /**
+     * @param event
+     * @return The node ID if the message contains it; "", otherwise
+     */
+    public static String getNodeID(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        XmlElement idElement = getIDElement(event);
+        String nodeID = null;
+        if (idElement != null) {
+            nodeID = idElement.attributeValue(WOR_NS, WORKFLOW_NODE_ID_ATTRIBUTE);
+        }
+        if(nodeID == null){
+           nodeID = event.element(NOTIFICATION_SOURCE_TAG).attributeValue(WOR_NS, WORKFLOW_NODE_ID_ATTRIBUTE);
+        }
+        if (nodeID == null) {
+            nodeID = "";
+        }
+        return nodeID;
+    }
+
+    /**
+     * @param event
+     * @return The node ID if the message contains it; "", otherwise
+     */
+    public static String getExperiementID(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        XmlElement idElement = event.element(WOR_NS,NOTIFICATION_SOURCE_TAG);
+        String nodeID = null;
+        if (idElement != null) {
+            nodeID = idElement.attributeValue(WOR_NS, WORKFLOW_EXPERIMENT_ID);
+        }if(nodeID == null){
+           nodeID = event.element(NOTIFICATION_SOURCE_TAG).attributeValue(WOR_NS, WORKFLOW_EXPERIMENT_ID);
+        }
+        if (nodeID == null) {
+            nodeID = "";
+        }
+        return nodeID;
+    }
+
+    /**
+     * @param event
+     * @return The workflow instance ID. null if there is no workflow instance ID.
+     */
+    public static URI getWorkflowID(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        EventType type = getType(event);
+        XmlElement idElement = getIDElement(event);
+        if (idElement == null) {
+            return null;
+        }
+
+        String workflowID;
+        switch (type) {
+        case WORKFLOW_INITIALIZED:
+        case WORKFLOW_TERMINATED:
+            // Special cases
+            workflowID = idElement.attributeValue(WOR_NS, SERVICE_ID_ATTRIBUTE);
+            break;
+        default:
+            // Default
+            workflowID = idElement.attributeValue(WOR_NS, WORKFLOW_ID_ATTRIBUTE);
+            break;
+        }
+        if (workflowID == null || workflowID.length() == 0) {
+            return null;
+        }
+        try {
+            return new URI(workflowID);
+        } catch (URISyntaxException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * @param event
+     * @return The type of the event to display
+     */
+    public static String getStatus(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        EventType type = getType(event);
+        String status;
+        switch (type) {
+        case LOG_INFO:
+            status = "INFO";
+            break;
+        case LOG_EXCEPTION:
+            status = "EXCEPTION";
+            break;
+        case LOG_WARNING:
+            status = "WARNING";
+            break;
+        case LOG_DEBUG:
+            status = "DEBUG";
+            break;
+        default:
+            status = event.getName();
+        }
+        return status;
+    }
+
+    /**
+     * @param event
+     * @return The message to display.
+     */
+    public static String getMessage(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        String description = null;
+        XmlElement descElement = event.element(WOR_NS, DESCRIPTION_TAG);
+        if (descElement != null) {
+            description = descElement.requiredText();
+        }
+
+        if (description == null || description.length() == 0) {
+            // It might be a data-related notification
+            XmlElement dataProduct = event.element(WOR_NS, DATA_PRODUCT_TAG);
+            if (dataProduct != null) {
+                descElement = dataProduct.element(WOR_NS, DESCRIPTION_TAG);
+                if (descElement != null) {
+                    description = descElement.requiredText();
+                }
+            }
+        }
+
+        if (description == null) {
+            description = "";
+        }
+        return description;
+    }
+
+    /**
+     * @param event
+     * @return The location.
+     */
+    public static String getLocation(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        XmlElement locationEl = event.element(WOR_NS, LOCATION_TAG);
+        if (locationEl != null) {
+            String location = locationEl.requiredText();
+            return location;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the mapped resource from the event.
+     * 
+     * @param event
+     *            The event, the type of which has to be resourceMapping.
+     * @return The resource
+     */
+    public static String getMappedResource(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        EventType type = getType(event);
+        if (type != EventType.RESOURCE_MAPPING) {
+            throw new IllegalArgumentException("Event must have resourceMapping type instead of " + type);
+        }
+        XmlElement mappedResource = event.element(MAPPED_RESOURCE_TAG);
+        String resource = mappedResource.requiredText();
+        return resource;
+    }
+
+    /**
+     * Gets the retry count from the event.
+     * 
+     * @param event
+     *            The event, the type of which has to be resourceMapping.
+     * @return The resource
+     */
+    public static String getRetryCount(XmlElement event) {
+        if (event == null) {
+            throw new IllegalArgumentException("null");
+        }
+        EventType type = getType(event);
+        if (type != EventType.RESOURCE_MAPPING) {
+            throw new IllegalArgumentException("Event must have resourceMapping type instead of " + type);
+        }
+        XmlElement retryCountElement = event.element(RETRY_STATUS_COUNT_TAG);
+        String retryCount = retryCountElement.requiredText();
+        return retryCount;
+    }
+
+    /**
+     * Gets the workflow instance ID.
+     * 
+     * @param event
+     *            The event, the type of which has to be workflowInitialized.
+     * @return The workflowInstanceID
+     */
+    public static URI getWorkflowInstanceID(XmlElement event) {
+        EventType type = getType(event);
+        if (!(type == EventType.WORKFLOW_INITIALIZED || type == EventType.WORKFLOW_TERMINATED)) {
+            throw new IllegalArgumentException(
+                    "Event must be an workflowInitialized type or an workflowTerminated type instead of " + type);
+        }
+        XmlElement notificationSource = event.element(WOR_NS, NOTIFICATION_SOURCE_TAG);
+        if (notificationSource == null) {
+            throw new WorkflowRuntimeException("The notification should have " + NOTIFICATION_SOURCE_TAG + " element.");
+        }
+        String workflowInstanceID = notificationSource.attributeValue(WOR_NS, SERVICE_ID_ATTRIBUTE);
+        if (workflowInstanceID == null) {
+            throw new WorkflowRuntimeException("The notification should have " + SERVICE_ID_ATTRIBUTE + " attribute.");
+        }
+        try {
+            return new URI(workflowInstanceID);
+        } catch (URISyntaxException e) {
+            throw new WorkflowRuntimeException(e);
+        }
+    }
+
+    /**
+     * @param event
+     * @return The element that has workflow ID, node ID, etc.
+     */
+    private static XmlElement getIDElement(XmlElement event) {
+        EventType type = getType(event);
+        switch (type) {
+        // The following three don't include node ID, but includes workflow ID.
+        case WORKFLOW_INITIALIZED:
+        case WORKFLOW_INVOKED:
+        case WORKFLOW_TERMINATED:
+            // The followings include both workflow ID and node ID.
+            // TODO they might be used by a workflow too.
+        case SERVICE_INVOKED:
+        case SENDING_RESULT:
+        case SENDING_FAULT:
+        case SENDING_RESPONSE_FAILED: // TODO make sure
+            // The followings are used only in services.
+        case LOG_INFO:
+        case LOG_WARNING:
+        case LOG_EXCEPTION:
+        case LOG_DEBUG:
+        case DATA_CONSUMED:
+        case DATA_PRODUCED:
+        case DATA_RECEIVE_DURATION:
+        case APPLICATION_AUDIT:
+        case COMPUTATION_DURATION:
+        case RESOURCE_MAPPING:
+        case PUBLISH_URL:
+        case INVOKING_SERVICE:
+                return event.element(RECEIVER_TAG);
+        case INVOKING_SERVICE_SUCCEEDED: // TODO make sure
+        case INVOKING_SERVICE_FAILED: // TODO make sure
+            return event.element(RECEIVER_TAG);
+        case RECEIVED_RESULT:
+        case RECEIVED_FAULT:
+            return event.element(RESPONDER_TAG);
+        case UNKNOWN:
+            // Most of unknown types are from service.
+            return event.element(NOTIFICATION_SOURCE_TAG);
+        default:
+            // Most of unknown types are from service.
+            return event.element(NOTIFICATION_SOURCE_TAG);
+        }
+    }
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/WsmgClient.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/WsmgClient.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/WsmgClient.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/WsmgClient.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,165 @@
+/*
+ *
+ * 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.ws.monitor;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.wsmg.client.ConsumerNotificationHandler;
+import org.apache.airavata.wsmg.client.MsgBrokerClientException;
+import org.apache.airavata.wsmg.client.NotificationHandler;
+import org.apache.airavata.wsmg.client.WseMsgBrokerClient;
+import org.apache.airavata.wsmg.client.msgbox.MessagePuller;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axis2.addressing.EndpointReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+public class WsmgClient implements ConsumerNotificationHandler, NotificationHandler {
+
+    private static final Logger logger = LoggerFactory.getLogger(WsmgClient.class);
+
+    private Monitor monitor;
+
+    private URI brokerURL;
+
+    private String topic;
+
+    private boolean pullMode;
+
+    private URI messageBoxURL;
+
+    private WseMsgBrokerClient wseClient;
+
+    private String subscriptionID;
+
+    private MessagePuller messagePuller;
+
+    private long timeout = 20000L;
+
+    private long interval = 1000L;
+    /**
+     * Constructs a WsmgClient.
+     * 
+     * @param monitor
+     */
+    public WsmgClient(Monitor monitor) {
+        this.monitor = monitor;
+
+        MonitorConfiguration configuration = monitor.getConfiguration();
+        // We need to copy these because the configuration might change.
+        this.brokerURL = configuration.getBrokerURL();
+        this.topic = configuration.getTopic();
+        this.pullMode = configuration.isPullMode();
+        this.messageBoxURL = configuration.getMessageBoxURL();
+
+        this.wseClient = new WseMsgBrokerClient();
+        this.wseClient.init(this.brokerURL.toString());
+    }
+
+    /**
+     * Subscribes to the notification.
+     * 
+     * @throws MonitorException
+     */
+    public synchronized void subscribe() throws MonitorException {
+        try {
+            if (this.pullMode) {
+                EndpointReference messageBoxEPR = this.wseClient.createPullMsgBox(this.messageBoxURL.toString(),getTimeout());
+                this.subscriptionID = this.wseClient.subscribe(messageBoxEPR.getAddress(), this.topic, null);
+                this.messagePuller = this.wseClient.startPullingEventsFromMsgBox(messageBoxEPR, this, getInterval(), getTimeout());
+            } else {
+                String[] endpoints = this.wseClient.startConsumerService(2222, this);
+                this.subscriptionID = this.wseClient.subscribe(endpoints[0], this.topic, null);
+            }
+        } catch (IOException e) {
+            throw new MonitorException("Failed to subscribe.", e);
+        } catch (RuntimeException e) {
+            throw new MonitorException("Failed to subscribe.", e);
+        }
+    }
+
+    /**
+     * Unsubscribes from the notification.
+     * 
+     * @throws MonitorException
+     */
+    public synchronized void unsubscribe() throws MonitorException {
+        // This method needs to be synchronized along with subscribe() because
+        // unsubscribe() might be called while subscribe() is being executed.
+        if (this.subscriptionID == null) {
+            throw new IllegalStateException();
+        }
+        try {
+            if (this.pullMode) {
+                this.messagePuller.stopPulling();
+            } else {
+                this.wseClient.shutdownConsumerService();
+            }
+            this.wseClient.unSubscribe(this.subscriptionID);
+        } catch (MsgBrokerClientException e) {
+            throw new MonitorException("Failed to unsubscribe.", e);
+        }
+
+    }
+
+    /**
+     * @see org.apache.airavata.wsmg.client.NotificationHandler#handleNotification(java.lang.String)
+     */
+    public void handleNotification(SOAPEnvelope message) {
+        String soapBody = message.getBody().toString();
+        this.handleNotification(soapBody);
+    }
+
+    /**
+     * 
+     * @param message
+     */
+    public void handleNotification(String message) {
+        try {
+            XmlElement event = XMLUtil.stringToXmlElement(message);
+            this.monitor.handleNotification(event);
+        } catch (Exception e) {
+            // Just log them because they can be unrelated messages sent to
+            // this topic by accident.
+            logger.warn("Could not parse received notification: " + message, e);
+        }
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public long getInterval() {
+        return interval;
+    }
+
+    public void setInterval(long interval) {
+        this.interval = interval;
+    }
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/Event.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/Event.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/Event.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/Event.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.ws.monitor.event;
+
+public class Event {
+
+    /**
+     */
+    public enum Type {
+        /**
+         * GPEL_CONFIGURATION_CHANGED
+         */
+        GPEL_CONFIGURATION_CHANGED,
+        /**
+         * GPEL_CONNECTED
+         */
+        GPEL_ENGINE_CONNECTED,
+        /**
+         * GPEL_ENGINE_DISCONNECTED
+         */
+        GPEL_ENGINE_DISCONNECTED,
+
+        /**
+         * MONITOR_CONFIGURATION_CHANGED
+         */
+        MONITOR_CONFIGURATION_CHANGED,
+        /**
+         * MONITOR_STARTED
+         */
+        MONITOR_STARTED,
+        /**
+         * MONITOR_STOPED
+         */
+        MONITOR_STOPED,
+
+        /**
+         * KARMA_STARTED
+         */
+        KARMA_STARTED,
+
+        /**
+         * MYLEAD_CONFIGURATION_CHANGED
+         */
+        MYLEAD_CONFIGURATION_CHANGED,
+    }
+
+    private Type type;
+
+    /**
+     * Constructs a Event.
+     * 
+     * @param type
+     */
+    public Event(Type type) {
+        this.type = type;
+    }
+
+    /**
+     * @return The type of the event
+     */
+    public Type getType() {
+        return this.type;
+    }
+
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventListener.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventListener.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventListener.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventListener.java Mon Nov 19 17:05:10 2012
@@ -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.ws.monitor.event;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+
+public interface EventListener {
+
+    /**
+     * Called when an event is received.
+     * 
+     * @param event
+     * @throws WorkflowException
+     */
+    public void eventReceived(Event event) throws WorkflowException;
+}
\ No newline at end of file

Added: airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventProducer.java
URL: http://svn.apache.org/viewvc/airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventProducer.java?rev=1411310&view=auto
==============================================================================
--- airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventProducer.java (added)
+++ airavata/trunk/modules/ws-messenger/message-monitor/src/main/java/org/apache/airavata/ws/monitor/event/EventProducer.java Mon Nov 19 17:05:10 2012
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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.ws.monitor.event;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class EventProducer {
+
+    private static final Logger logger = LoggerFactory.getLogger(EventProducer.class);
+
+    private List<EventListener> listeners = new LinkedList<EventListener>();
+
+    /**
+     * @param listener
+     */
+    public void addEventListener(EventListener listener) {
+        this.listeners.add(listener);
+    }
+
+    /**
+     * @param listener
+     */
+    public void removeEventListener(EventListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    /**
+     * @param event
+     */
+    public void sendSafeEvent(Event event) {
+        Throwable exception = null;
+        for (EventListener listener : this.listeners) {
+            try {
+                listener.eventReceived(event);
+            } catch (Throwable e) {
+                logger.error(e.getMessage(), e);
+                // Just remember the first one.
+                if (exception == null) {
+                    exception = e;
+                }
+            }
+        }
+        if (exception != null) {
+            if (exception instanceof RuntimeException) {
+                throw (RuntimeException) exception;
+            } else {
+                throw new WorkflowRuntimeException(exception);
+            }
+        }
+    }
+
+    /**
+     * Sends an event.
+     * 
+     * @param event
+     * @throws WorkflowException
+     */
+    public void sendEvent(Event event) throws WorkflowException {
+        Throwable exception = null;
+        for (EventListener listener : this.listeners) {
+            try {
+                listener.eventReceived(event);
+            } catch (Throwable e) {
+                logger.error(e.getMessage(), e);
+                // Just remember the first one.
+                if (exception == null) {
+                    exception = e;
+                }
+            }
+        }
+        if (exception != null) {
+            if (exception instanceof WorkflowException) {
+                throw (WorkflowException) exception;
+            } else {
+                throw new WorkflowException(exception);
+            }
+        }
+    }
+
+}
\ No newline at end of file