You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by ma...@apache.org on 2017/01/23 10:30:27 UTC

portals-pluto git commit: First working implementation of cross context cdi events.

Repository: portals-pluto
Updated Branches:
  refs/heads/cross-context-cdi-events [created] 982077a9e


First working implementation of cross context cdi events.


Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/982077a9
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/982077a9
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/982077a9

Branch: refs/heads/cross-context-cdi-events
Commit: 982077a9e2145e0f0dd8e261c5e8510100f3adf3
Parents: c5fba6a
Author: ahmed <ma...@gmail.com>
Authored: Mon Jan 23 11:19:39 2017 +0100
Committer: ahmed <ma...@gmail.com>
Committed: Mon Jan 23 11:19:39 2017 +0100

----------------------------------------------------------------------
 .../apache/pluto/container/EventProvider.java   |   2 +
 .../container/driver/PortletContextService.java |   4 +
 .../pluto/container/driver/PortletServlet3.java | 248 ++++++-
 .../bean/processor/CDIEventsStore.java          |  56 ++
 .../bean/processor/CrossContextObserver.java    |  72 ++
 .../container/bean/processor/EmptyEvent.java    |  29 +
 .../container/bean/processor/MyEmptyEvent.java  |   7 +
 .../bean/processor/MyPortletEvent.java          |   7 +
 .../bean/processor/PortletCDIEvent.java         |  80 ++
 .../processor/PortletCDIEventExtension.java     | 735 +++++++++++++++++++
 .../container/bean/processor/PortletEvent.java  |  29 +
 .../container/impl/StateAwareResponseImpl.java  |  24 +-
 .../javax.enterprise.inject.spi.Extension       |   3 +-
 .../container/EventCoordinationServiceImpl.java |  92 ++-
 .../services/container/EventProviderImpl.java   |  27 +-
 .../driver/container/PortletContextManager.java |   5 +
 16 files changed, 1374 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container-api/src/main/java/org/apache/pluto/container/EventProvider.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/EventProvider.java b/pluto-container-api/src/main/java/org/apache/pluto/container/EventProvider.java
index 1728f2a..67676cd 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/EventProvider.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/EventProvider.java
@@ -31,4 +31,6 @@ public interface EventProvider {
 
     Event createEvent(QName name, Serializable value)
     throws IllegalArgumentException;
+
+    Event createCDIEvent(QName qname, Serializable value) throws IllegalArgumentException;
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
----------------------------------------------------------------------
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
index 82d268c..ffda1eb 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
@@ -22,6 +22,7 @@ import javax.servlet.ServletConfig;
 
 import org.apache.pluto.container.PortletContainerException;
 import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
 
 /**
  * Interface defining the services used by both the Pluto Portal Driver
@@ -95,4 +96,7 @@ public interface PortletContextService
      * @param context
      */
     void unregister(DriverPortletContext context);
+    
+    //TODO: Document this function
+    public void updatePortletConfig(DriverPortletContext portletContext, PortletDefinition portletDefinition);
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
----------------------------------------------------------------------
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
index de3bf94..926785a 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
@@ -18,7 +18,15 @@ package org.apache.pluto.container.driver;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringReader;
 import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -30,6 +38,7 @@ import javax.naming.InitialContext;
 import javax.naming.NameNotFoundException;
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
+import javax.portlet.Event;
 import javax.portlet.EventRequest;
 import javax.portlet.EventResponse;
 import javax.portlet.HeaderRequest;
@@ -55,6 +64,16 @@ import javax.servlet.ServletResponseWrapper;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
 
 import org.apache.pluto.container.FilterManager;
 import org.apache.pluto.container.PortletAsyncManager;
@@ -65,13 +84,21 @@ import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.PortletWindow;
 import org.apache.pluto.container.bean.processor.AnnotatedConfigBean;
+import org.apache.pluto.container.bean.processor.CDIEventsStore;
 import org.apache.pluto.container.bean.processor.PortletArtifactProducer;
+import org.apache.pluto.container.bean.processor.PortletCDIEvent;
 import org.apache.pluto.container.bean.processor.PortletInvoker;
 import org.apache.pluto.container.bean.processor.PortletRequestScopedBeanHolder;
 import org.apache.pluto.container.bean.processor.PortletSessionBeanHolder;
 import org.apache.pluto.container.bean.processor.PortletStateScopedBeanHolder;
 import org.apache.pluto.container.impl.HttpServletPortletRequestWrapper;
+import org.apache.pluto.container.om.portlet.EventDefinition;
+import org.apache.pluto.container.om.portlet.EventDefinitionReference;
+import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
 import org.apache.pluto.container.om.portlet.impl.ConfigurationHolder;
+import org.apache.pluto.container.om.portlet.impl.EventDefinitionImpl;
+import org.apache.pluto.container.om.portlet.impl.EventDefinitionReferenceImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -133,6 +160,8 @@ public class PortletServlet3 extends HttpServlet {
 
    private boolean                started = false;
    Timer                          startTimer;
+   
+   private static final QName CDI_EVENT_QNAME = new QName("javax.portlet.cdi.event", "javax.portlet.cdi.event");
 
    // HttpServlet Impl --------------------------------------------------------
 
@@ -261,11 +290,42 @@ public class PortletServlet3 extends HttpServlet {
                isOutOfService = true;
                return true;
             }
-
+            
             String applicationName = contextService.register(sConfig);
             started = true;
             portletContext = contextService.getPortletContext(applicationName);
             portletConfig = contextService.getPortletConfig(applicationName, portletName);
+            
+            // Get the portlet application definition
+            //PortletApplicationDefinition apd = portletContext.getPortletApplicationDefinition();
+            PortletApplicationDefinition pad = holder.getPad();
+            
+            PortletDefinition portletDefinition =pad.getPortlet(portletName);
+            
+            // Make a new Portlet event to correspond to CDI event
+            EventDefinition eventDefinition = new EventDefinitionImpl(CDI_EVENT_QNAME);
+            eventDefinition.setQName(CDI_EVENT_QNAME);
+            eventDefinition.setValueType("java.io.Serializable");
+            EventDefinitionReference eventDefinitionReference = new EventDefinitionReferenceImpl(CDI_EVENT_QNAME);
+            
+            // Add definition of new portlet CDI event to portlet application definition
+            if(pad.getEventDefinition(CDI_EVENT_QNAME)==null){
+               pad.addEventDefinition(eventDefinition);
+            }
+            
+            // Made this portlet publisher of the new portlet CDI event
+            portletDefinition.addSupportedPublishingEvent(eventDefinitionReference);
+            
+            // Add the modified portlet definition in portlet application definition  
+            
+            if(!CDIEventsStore.portletAdded.containsKey(pad)){          
+               // Made this portlet subscriber of the new portlet CDI event
+               portletDefinition.addSupportedProcessingEvent(eventDefinitionReference);
+               CDIEventsStore.portletAdded.put(pad, portletName);
+            } 
+            pad.addPortlet(portletDefinition);
+            contextService.updatePortletConfig(portletContext, portletDefinition);
+            
 
          } catch (PortletContainerException ex) {
             context.log(ex.getMessage(), ex);
@@ -515,13 +575,195 @@ public class PortletServlet3 extends HttpServlet {
             ActionRequest actionRequest = (ActionRequest) portletRequest;
             ActionResponse actionResponse = (ActionResponse) portletResponse;
             filterManager.processFilter(actionRequest, actionResponse, invoker, portletContext);
+            
+            // TODO: Document this
+            System.out.println("We have "+CDIEventsStore.universalEventList.size()+" events in universal event list.");
+            for(PortletCDIEvent newPortletCDIEvent : CDIEventsStore.universalEventList){
+               Object value = newPortletCDIEvent.getData();
+               if(value!=null){
+                  ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                  Writer out = new StringWriter();
+      
+                  try {
+                     @SuppressWarnings("rawtypes")
+                     Class clazz = value.getClass();
+                     System.setProperty( "com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize", "true");
+                     JAXBContext jc = JAXBContext.newInstance(clazz);
+                     Marshaller marshaller = jc.createMarshaller();
+                     JAXBElement<Serializable> element = new JAXBElement<Serializable>(CDI_EVENT_QNAME, clazz, (Serializable) value);
+                     marshaller.marshal(element, out);
+                     newPortletCDIEvent.setSerializedData(out.toString());
+                     actionResponse.setEvent(CDI_EVENT_QNAME, out.toString());
+                     // TODO: Check if the events has already been set in another portlet of the same web app
+                     /*
+                     
+                     PortletApplicationDefinition pad = holder.getPad();
+                     if(CDIEventsStore.portletAppCDIEventList.containsKey(pad)){
+                        Set<PortletCDIEvent> portletAppCDIEventList = CDIEventsStore.portletAppCDIEventList.get(pad);
+                        for(PortletCDIEvent existingPortletCDIEvent: portletAppCDIEventList){
+                           if(!existingPortletCDIEvent.equals(newPortletCDIEvent)){
+                              System.out.println("Wrongly set CDI portlet event again");
+                              portletAppCDIEventList.add(newPortletCDIEvent);
+                              CDIEventsStore.portletAppCDIEventList.put(pad, portletAppCDIEventList);
+                              actionResponse.setEvent(CDI_EVENT_QNAME, out.toString());
+                           } else {
+                              System.out.println("Skipped setting CDI portlet event because its already set by another portlet in the same web app");
+                           }
+                        }
+                     } else {
+                        System.out.println("Set CDI portlet event for the first time");
+                        Set<PortletCDIEvent> portletAppCDIEventList = new HashSet<PortletCDIEvent>();
+                        portletAppCDIEventList.add(newPortletCDIEvent);
+                        CDIEventsStore.portletAppCDIEventList.put(pad, portletAppCDIEventList);
+                        actionResponse.setEvent(CDI_EVENT_QNAME, out.toString());
+                     }
+                     */
+                     
+                  } catch(Exception e) {
+                     System.out.println("Error while serializing cdi event data "+e.toString());
+                     e.printStackTrace();
+                  } finally {
+                     Thread.currentThread().setContextClassLoader(cl);
+                     System.getProperties().remove("com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize");
+                  }
+               }
+            }
          }
 
-         // The request methode is Event: call Portlet.processEvent(..)
+         // The request method is Event: call Portlet.processEvent(..)
          else if (methodId == PortletInvokerService.METHOD_EVENT) {
             EventRequest eventRequest = (EventRequest) portletRequest;
             EventResponse eventResponse = (EventResponse) portletResponse;
-            filterManager.processFilter(eventRequest, eventResponse, invoker, portletContext);
+            System.out.println("Calling event method of "+portletName);
+            
+            // check if it is my cdi event
+            // then deserialize data, don't let invoker get control and fire the cdi event
+            
+            Event portletEvent = eventRequest.getEvent();
+            if(portletEvent!=null){
+               if(portletEvent.getQName().equals(CDI_EVENT_QNAME)){
+                  Object value = portletEvent.getValue();
+                  XMLStreamReader xml = null;
+                  try {
+                     if (value instanceof String) {
+                        String in = (String) value;
+                        xml = XMLInputFactory.newInstance().createXMLStreamReader(
+                              new StringReader(in));
+                     } 
+                  } catch (XMLStreamException e1) {
+                     System.out.println(e1.toString());
+                     throw new IllegalStateException(e1);
+                  } catch (FactoryConfigurationError e1) {
+                     System.out.println(e1.toString());
+                     throw new IllegalStateException(e1);
+                  }
+
+                  if (xml != null) {
+                     try {
+                        System.out.println("Universal event list size is "+CDIEventsStore.universalEventList.size());
+                        for(PortletCDIEvent portletCDIEvent : CDIEventsStore.universalEventList){
+                           if(portletCDIEvent.getData().equals(value)){
+                              ClassLoader loader = portletContext.getClassLoader();
+                              Class<? extends Serializable> clazz = loader.loadClass(
+                                    portletCDIEvent.getDataType()).asSubclass(
+                                    Serializable.class);
+               
+                              JAXBContext jc = JAXBContext.newInstance(clazz);
+                              Unmarshaller unmarshaller = jc.createUnmarshaller();
+               
+                              JAXBElement result = unmarshaller.unmarshal(xml, clazz);
+               
+                              try{
+                                    System.out.println("Now firing event from bean manager");
+                                    // TODO: Check if the event has already been fired before
+                                    //       by another portlet of the same web app
+                                    CDIEventsStore.firedFromBeanManager=true;
+                                    beanmgr.fireEvent(result.getValue(), portletCDIEvent.getQualifiers());
+                                    CDIEventsStore.firedFromBeanManager=false;
+                              } catch (Exception e){
+                                 e.printStackTrace();
+                              }
+                           }
+                        }
+                        /*
+                        boolean contains = false;
+                        for(String portletName : CDIEventsStore.recieverPortlets){
+                           if(this.portletName.equals(portletName)){
+                              contains = true;
+                              break;
+                           }
+                        }
+                        if(!contains){
+                           for(PortletCDIEvent portletCDIEvent : CDIEventsStore.universalEventList){
+                              if(portletCDIEvent.getData().equals(value)){
+                                 ClassLoader loader = portletContext.getClassLoader();
+                                 Class<? extends Serializable> clazz = loader.loadClass(
+                                       portletCDIEvent.getDataType()).asSubclass(
+                                       Serializable.class);
+                  
+                                 JAXBContext jc = JAXBContext.newInstance(clazz);
+                                 Unmarshaller unmarshaller = jc.createUnmarshaller();
+                  
+                                 JAXBElement result = unmarshaller.unmarshal(xml, clazz);
+                  
+                                 try{
+                                       System.out.println("Now firing event from bean manager");
+                                       // TODO: Check if the event has already been fired before
+                                       //       by another portlet of the same web app
+                                       CDIEventsStore.firedFromBeanManager=true;
+                                       beanmgr.fireEvent(result.getValue(), portletCDIEvent.getQualifiers());
+                                       PortletApplicationDefinition pad = holder.getPad();
+                                       List<PortletDefinition> portlets = pad.getPortlets();
+                                       for(PortletDefinition portlet : portlets){
+                                          CDIEventsStore.recieverPortlets.remove(portlet.getPortletName());
+                                       }
+                                       if(CDIEventsStore.recieverPortlets.isEmpty()){
+                                          CDIEventsStore.universalEventList.clear();
+                                       }
+                                       CDIEventsStore.firedFromBeanManager=false;
+                                 } catch (Exception e){
+                                    e.printStackTrace();
+                                 }
+                              }
+                           }
+                        }
+                        */
+                        /*Set<Entry<PortletApplicationDefinition, Set<PortletCDIEvent>>> portletAppCDIEventList = CDIEventsStore.portletAppCDIEventList.entrySet();
+                        for(Entry<PortletApplicationDefinition, Set<PortletCDIEvent>> iterator : portletAppCDIEventList){
+                           if(pad.equals(iterator.getKey())){
+                              for(PortletCDIEvent portletCDIEvent : iterator.getValue()){
+                                 if(portletCDIEvent.getData().equals(value)){
+                                    contains = true;
+                                    break;
+                                 }
+                              }
+                              if(contains){
+                                 break;
+                              }
+                           }
+                        }
+                        */
+                        
+                       
+                     } catch (JAXBException e) {
+                        System.out.println(e.toString());
+                        throw new IllegalStateException(e);
+                     } catch (ClassCastException e) {
+                        System.out.println(e.toString());
+                        throw new IllegalStateException(e);
+                     } catch (ClassNotFoundException e) {
+                       System.out.println(e.toString());
+                        throw new IllegalStateException(e);
+                     }
+                  }
+                  
+                  
+               } else {
+                  filterManager.processFilter(eventRequest, eventResponse, invoker, portletContext);
+               }
+            } else {
+               System.out.println("Portlet Event is null.");
+            }
          }
          // The requested method is ADMIN: call handlers.
          else if (methodId == PortletInvokerService.METHOD_ADMIN) {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CDIEventsStore.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CDIEventsStore.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CDIEventsStore.java
new file mode 100644
index 0000000..a83a60e
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CDIEventsStore.java
@@ -0,0 +1,56 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+
+@ApplicationScoped
+public class CDIEventsStore {
+   
+   public static Map<AnnotatedField<?>, HashSet<ObserverMethod<?>>> event_observers = Collections.synchronizedMap(new HashMap<AnnotatedField<?>, HashSet<ObserverMethod<?>>>());
+   public static Map<ObserverMethod<?>, Object> observerInvocation = Collections.synchronizedMap(new HashMap<ObserverMethod<?>, Object>());
+   public static Map<Object, Set<Annotation>> eventStore = Collections.synchronizedMap(new HashMap<Object, Set<Annotation>>());
+   public static ArrayList<PortletCDIEvent> universalEventList = new ArrayList<PortletCDIEvent>();
+   public static ArrayList<ObserverMethod<?>> universalObserverList = new ArrayList<ObserverMethod<?>>();
+   public static boolean firedFromBeanManager = false; 
+   public static Set<String> recieverPortlets = new HashSet<String>();
+   public static Map<PortletApplicationDefinition, Set<PortletCDIEvent>> portletAppCDIEventList = Collections.synchronizedMap(new HashMap<PortletApplicationDefinition, Set<PortletCDIEvent>>());
+   public static Map<PortletApplicationDefinition, String> portletAdded = Collections.synchronizedMap(new HashMap<PortletApplicationDefinition, String>());
+   public static Stack<Map<PortletApplicationDefinition, String>> lifo = new Stack<Map<PortletApplicationDefinition, String>>();
+   
+   public static synchronized void addEventToUniversalList(PortletCDIEvent newPortletCDIEvent){
+      boolean contains = false;
+      for(PortletCDIEvent PortletCDIEvent : universalEventList){
+         if(PortletCDIEvent.equals(newPortletCDIEvent)){
+            if(!PortletCDIEvent.getObserverBeanClass().equals(newPortletCDIEvent.getObserverBeanClass())){
+               contains = true;
+               break;
+            }
+         }
+      }
+      if(!contains){
+         universalEventList.add(newPortletCDIEvent);
+      }
+   }
+   
+   /*
+   public static void printInvokedObservers(){
+      Set<Entry<ObserverMethod<?>, Serializable>> observerInvokation = CDIEventsStore.observerInvocation.entrySet();
+      for(Entry<ObserverMethod<?>, Serializable> hi : observerInvokation){
+         System.out.println(hi.getValue().toString());
+      }
+   }
+   */
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CrossContextObserver.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CrossContextObserver.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CrossContextObserver.java
new file mode 100644
index 0000000..b6346b3
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/CrossContextObserver.java
@@ -0,0 +1,72 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.enterprise.event.Reception;
+import javax.enterprise.event.TransactionPhase;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+public class CrossContextObserver implements ObserverMethod<Object>{
+
+   private Type type;
+   private Class<?> clas;
+   private Set<Annotation> annotations;
+   private Reception reception;
+   //private TransactionPhase transaction;
+   
+   @Override
+   public Class<?> getBeanClass() {
+      return clas;
+   }
+   
+   public void setBeanClass(Class<?> clas) {
+      this.clas = clas;
+   }
+
+   @Override
+   public Type getObservedType() {
+      return type;
+   }
+   
+   public void setObservedType(Type type) {
+      this.type = type;
+   }
+
+   @Override
+   public Set<Annotation> getObservedQualifiers() {
+      return annotations;
+   }
+   
+   public void setObservedQualifiers(Set<Annotation> annotations) {
+      this.annotations = annotations;
+   }
+
+   @Override
+   public Reception getReception() {
+      return reception;
+   }
+   
+   public void setReception(Reception reception) {
+      this.reception = reception;
+   }
+
+   @Override
+   public TransactionPhase getTransactionPhase() {
+      return TransactionPhase.BEFORE_COMPLETION;
+   }
+   
+   /*
+   public void setTransactionPhase(TransactionPhase transaction) {
+      this.transaction = transaction;
+   }
+   */
+
+   @Override
+   public void notify(Object data) {
+      System.out.println("CrossContextObserver recieved = " + data.toString());
+      throw new IllegalArgumentException("Cross Context Eventing Mechanism caught the event and blocked it");
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/EmptyEvent.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/EmptyEvent.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/EmptyEvent.java
new file mode 100644
index 0000000..a02e0ae
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/EmptyEvent.java
@@ -0,0 +1,29 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.METHOD;
+
+import javax.inject.Qualifier;
+
+/**
+ * An annotation that is used as a qualifier for events fired when
+ * a name is added.
+ * 
+ * @author nick
+ *
+ */
+/* 
+ * Just making a new annotation for our event.
+ * What we learn from here is not only implementations
+ * but also events can be specified as a Qualifier.
+ * To see the usage - See FormController class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+@Target({FIELD, METHOD, PARAMETER, TYPE})
+public @interface EmptyEvent {}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyEmptyEvent.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyEmptyEvent.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyEmptyEvent.java
new file mode 100644
index 0000000..406890e
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyEmptyEvent.java
@@ -0,0 +1,7 @@
+package org.apache.pluto.container.bean.processor;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+public class MyEmptyEvent extends AnnotationLiteral<EmptyEvent> implements EmptyEvent {
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyPortletEvent.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyPortletEvent.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyPortletEvent.java
new file mode 100644
index 0000000..381addb
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/MyPortletEvent.java
@@ -0,0 +1,7 @@
+package org.apache.pluto.container.bean.processor;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+public class MyPortletEvent extends AnnotationLiteral<PortletEvent> implements PortletEvent {
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEvent.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEvent.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEvent.java
new file mode 100644
index 0000000..f056fca
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEvent.java
@@ -0,0 +1,80 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+public class PortletCDIEvent {
+
+   private Annotation[] qualifiers;
+   private int          no_of_qualifiers;
+   private Object data;
+   private String dataType;
+   private Class observerBeanClass;
+
+   public PortletCDIEvent(Set<Annotation> qualifiers, Object data, Class observerBeanClass) {
+      this.qualifiers = new Annotation[qualifiers.size()];
+      int count = 0;
+      for(Annotation qualifier : qualifiers){
+         this.qualifiers[count]=qualifier;
+         count++;
+      }
+      this.no_of_qualifiers = qualifiers.size();
+      this.data = data;
+      this.dataType = data.getClass().getCanonicalName();
+      this.observerBeanClass=observerBeanClass;
+   }
+
+   public Annotation[] getQualifiers() {
+      return qualifiers;
+   }
+
+   public int get_no_of_qualifiers() {
+      return no_of_qualifiers;
+   }
+
+   public Object getData() {
+      return data;
+   }
+   
+   public void setSerializedData(Serializable data) {
+      this.data = data;
+   }
+   
+   public String getDataType() {
+      return dataType;
+   }
+   
+   public Class getObserverBeanClass() {
+      return observerBeanClass;
+   }
+
+   
+   // TODO: Maybe throw exceptions when equals return false
+   // TODO: Check if we can set same CDI event 2 times  
+   @Override
+   public boolean equals(Object obj){
+      if(obj instanceof PortletCDIEvent){
+         PortletCDIEvent comparedObj = (PortletCDIEvent) obj;
+         if(this.no_of_qualifiers != comparedObj.no_of_qualifiers){
+            //System.out.println("Comparison returned false because no of qualifiers are different");
+            return false;
+         }
+         for(int i=0; i<this.no_of_qualifiers;i++){
+            if(!this.qualifiers[i].equals(comparedObj.qualifiers[i])){
+               //System.out.println("Comparison returned false because qualifers are different. Particularly "+ this.qualifiers[i].toString());
+               return false;
+            }
+         }
+         /*if(!this.data.equals(comparedObj.data)){
+            //System.out.println("Comparison returned false because data is different. "+this.data.toString()+" != "+comparedObj.data.toString());
+            return false;
+         }*/
+         return true;
+      } else {
+         return false;
+      }
+      
+   }
+   
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEventExtension.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEventExtension.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEventExtension.java
new file mode 100644
index 0000000..94f2141
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletCDIEventExtension.java
@@ -0,0 +1,735 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.event.Reception;
+import javax.enterprise.event.TransactionPhase;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedCallable;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ObserverMethod;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessObserverMethod;
+import javax.inject.Inject;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class PortletCDIEventExtension implements Extension {
+   
+   private static final Logger LOG = LoggerFactory.getLogger(PortletCDIEventExtension.class);
+   
+   // To make reference to class fields which are currently examined
+   private HashSet<AnnotatedField<?>> fieldsInCurrentScope = new HashSet<AnnotatedField<?>>();
+   
+   // To make reference to the original observers 
+   private HashSet<ObserverMethod<?>> originalObserverMethods = new HashSet<ObserverMethod<?>>();
+
+   // Starting the scanning process 
+   void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) {
+      LOG.debug("PortletCDIEventExtension - scanning.");
+   }
+
+   // Scan all classes with javax.enterprise.event.Event field
+   <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat) {
+
+      final AnnotatedType<T> at = pat.getAnnotatedType();
+
+      // Get all fields of the class
+      Set<AnnotatedField<? super T>> fields = at.getFields();
+      
+      final Set<AnnotatedField<? super T>> modifiedFields = new HashSet<AnnotatedField<? super T>>();
+      
+      //TODO: See if I am only getting annotated field else use reflection API
+      
+      // Iterate through all fields
+      for (final AnnotatedField<? super T> field : fields) {
+         
+         // Get full name of field with modifiers, annotations and type
+         String fieldFullName = field.toString();
+         
+         // Short-listing fields with @Inject annotation
+         if (fieldFullName.contains("@Inject")) {
+            // Get the full class name of field type
+            // check if its equal to javax.enterprise.event.Event
+            if (field.getBaseType().toString()
+                  .contains("javax.enterprise.event.Event")) {
+               
+               // Add the CDI event declaration in event_observers map
+               // For now, just put an empty HashSet of observers for this event
+               // Later, in processObserverMethod we will try to find 
+               // all observers associated with this event
+               
+               
+               final Set<Annotation> newAnnotations = new LinkedHashSet<Annotation>();
+               List<Annotation> newAnnotationsList = new ArrayList<Annotation>();
+               
+               System.out.println("\nBefore adding @EmptyEvent - \n");
+               for(Annotation annotation : field.getAnnotations()){
+                  System.out.println(annotation.toString());
+                  // Add all original annotations in the same order in the linked list
+                  newAnnotationsList.add(annotation);
+               }
+               
+               // Make the @PortletEvent qualifier
+               Annotation emptyEventAnnotation = new MyEmptyEvent();
+
+               // Add @PortletEvent annotation as last qualifier in the linked list
+               newAnnotationsList.add(emptyEventAnnotation);
+
+               // Add all the annotations from linked list to the new annotation set
+               // again maintaining the same order of annotations
+               for(int i=0;i<newAnnotationsList.size();i++){
+                  newAnnotations.add(newAnnotationsList.get(i));
+               }
+               
+               // Print the modified annotations
+               System.out.println("\nAfter adding @EmptyEvent - \n");
+               for(Annotation annotation : newAnnotations){
+                  System.out.println(annotation.toString());
+               }
+               
+               AnnotatedField<T> annotatedField = new AnnotatedField<T>(){
+
+                  @Override
+                  public boolean isStatic() {
+                     return field.isStatic();
+                  }
+
+                  @Override
+                  public AnnotatedType<T> getDeclaringType() {
+                     return (AnnotatedType<T>) field.getDeclaringType();
+                  }
+
+                  @Override
+                  public Type getBaseType() {
+                     return field.getBaseType();
+                  }
+
+                  @Override
+                  public Set<Type> getTypeClosure() {
+                     return field.getTypeClosure();
+                  }
+
+                  @Override
+                  public <T extends Annotation> T getAnnotation(
+                        Class<T> annotationType) {
+                     return field.getAnnotation(annotationType);
+                  }
+
+                  @Override
+                  public Set<Annotation> getAnnotations() {
+                     return newAnnotations;
+                  }
+
+                  @Override
+                  public boolean isAnnotationPresent(
+                        Class<? extends Annotation> annotationType) {
+                     return field.isAnnotationPresent(annotationType);
+                  }
+
+                  @Override
+                  public Field getJavaMember() {
+                     return field.getJavaMember();
+                  }
+                  
+               };
+               
+               modifiedFields.add(annotatedField);
+               
+               CDIEventsStore.event_observers.put(annotatedField, new HashSet<ObserverMethod<?>>());
+               fieldsInCurrentScope.add(annotatedField);
+               
+               // Commenting out the code to match event and observers of different web apps
+               for (Map.Entry<AnnotatedField<?>, HashSet<ObserverMethod<?>>> entry : CDIEventsStore.event_observers.entrySet())
+               {
+                  HashSet<ObserverMethod<?>> observerMethods = entry.getValue();
+                  for (ObserverMethod<?> observer : observerMethods) {
+                     if(compareEventAndObserver(annotatedField, observer)){
+                        CDIEventsStore.event_observers.get(annotatedField).add(observer);
+                     }
+                  }
+               }
+            } else {
+               modifiedFields.add(field);
+            }
+         } else {
+            modifiedFields.add(field);
+         }
+      }
+      
+      
+      
+      
+      /* Scanner for observers at processing annotated types */
+      
+      // Get the class of annotated type
+      Class<?> className = pat.getAnnotatedType().getJavaClass();
+      
+      // Ignore Observers from PortletCDIExtension class and PortletCDIEventExtension class only
+      if(className!=null && !className.equals(PortletCDIEventExtension.class) && !className.equals(PortletCDIExtension.class)){
+         
+         // A set to add modified observer method
+         final Set<AnnotatedMethod<? super T>> newMethods = new HashSet<AnnotatedMethod<? super T>>();
+         
+         // set of methods in the scanned class
+         Set<AnnotatedMethod<? super T>> methods = at.getMethods();
+         
+         for (final AnnotatedMethod<? super T> method : methods) {
+            
+            // If the method contains @Observes annotation then it is an event observer
+            if (method.toString().contains("@Observes")) {
+               
+               // A list to modify parameter of the observer method
+               final List<AnnotatedParameter<T>> newParameters = new ArrayList<AnnotatedParameter<T>>();
+               
+               // A set to add @PortletEvent annotation in the set
+               // of annotations of the parameter of Observer method
+               final Set<Annotation> newAnnotations = new LinkedHashSet<Annotation>();
+               
+               // Making a linked list of new annotations because
+               // above set doesn't keep the annotation in the original order 
+               List<Annotation> newAnnotationsList = new ArrayList<Annotation>();
+               List<?> parameters1 = method.getParameters();
+               
+               // Get the first parameter of the observer method which contains all annotations
+               // TODO: Check if an observer can be defined with 2 parameters in which case this code will fail
+               final AnnotatedParameter<?> firstParameter = (AnnotatedParameter<?>)parameters1.get(0);
+
+               // Get all annotations of first parameter of observer method
+               Set<Annotation> firstParameterAnnotations = firstParameter.getAnnotations();
+               
+               newAnnotations.addAll(firstParameterAnnotations);
+               
+               System.out.println("\n\nBefore adding @PortletEvent - \n");
+               for(Annotation annotation : firstParameterAnnotations){
+                  System.out.println(annotation.toString());
+                  
+                  // Add all original annotations in the same order in the linked list
+                  newAnnotationsList.add(annotation);
+               }
+               
+               // Make the @PortletEvent qualifier
+               Annotation portletEventAnnotation = new MyPortletEvent();
+
+               // Add @PortletEvent annotation as last qualifier in the linked list
+               newAnnotationsList.add(portletEventAnnotation);
+
+               // Add all the annotations from linked list to the new annotation set
+               // again maintaining the same order of annotations
+               for(int i=0;i<newAnnotationsList.size();i++){
+                  newAnnotations.add(newAnnotationsList.get(i));
+               }
+               
+               // Print the modified annotations
+               System.out.println("\nAfter adding @PortletEvent - \n");
+               for(Annotation annotation : newAnnotations){
+                  System.out.println(annotation.toString());
+               }
+               
+               // Wrapper for first parameter of observer method
+               AnnotatedParameter<T> annotatedParameter = new AnnotatedParameter<T>(){
+
+                  @Override
+                  public Type getBaseType() {
+                     return firstParameter.getBaseType();
+                  }
+
+                  @Override
+                  public Set<Type> getTypeClosure() {
+                     return firstParameter.getTypeClosure();
+                  }
+
+                  @Override
+                  public <T extends Annotation> T getAnnotation(
+                        Class<T> annotationType) {
+                     return firstParameter.getAnnotation(annotationType);
+                  }
+
+                  @Override
+                  public Set<Annotation> getAnnotations() {
+                     // Only here we put the new annotation set which also include
+                     // @PortletEvent annotation
+                     return newAnnotations;
+                  }
+
+                  @Override
+                  public boolean isAnnotationPresent(
+                        Class<? extends Annotation> annotationType) {
+                     return firstParameter.isAnnotationPresent(annotationType);
+                  }
+
+                  @Override
+                  public int getPosition() {
+                     return firstParameter.getPosition();
+                  }
+
+                  @Override
+                  public AnnotatedCallable<T> getDeclaringCallable() {
+                     return (AnnotatedCallable<T>) firstParameter.getDeclaringCallable();
+                  }
+                  
+               };
+               
+               // We add the above wrapped parameter in the list of parameters
+               // of observer method
+               newParameters.add(annotatedParameter);
+               
+               // Wrapper for observer method
+               AnnotatedMethod<T> annotatedMethod = new AnnotatedMethod<T>() {
+
+                  @Override
+                  public List<AnnotatedParameter<T>> getParameters() {
+                     // Only here we the modified list of parameters
+                     return newParameters;
+                  }
+
+                  @Override
+                  public boolean isStatic() {
+                     return method.isStatic();
+                  }
+
+                  @Override
+                  public AnnotatedType<T> getDeclaringType() {
+                     return (AnnotatedType<T>) method.getDeclaringType();
+                  }
+
+                  @Override
+                  public Type getBaseType() {
+                     return method.getBaseType();
+                  }
+
+                  @Override
+                  public Set<Type> getTypeClosure() {
+                     return method.getTypeClosure();
+                  }
+
+                  @Override
+                  public <T extends Annotation> T getAnnotation(
+                        Class<T> annotationType) {
+                     return method.getAnnotation(annotationType);
+                  }
+
+                  @Override
+                  public Set<Annotation> getAnnotations() {
+                     return method.getAnnotations();
+                  }
+
+                  @Override
+                  public boolean isAnnotationPresent(
+                        Class<? extends Annotation> annotationType) {
+                     return method.isAnnotationPresent(annotationType);
+                  }
+
+                  @Override
+                  public Method getJavaMember() {
+                     return method.getJavaMember();
+                  }
+                  
+               };
+               
+               // We add the above wrapped observer method in set of methods of this class
+               newMethods.add(annotatedMethod);
+            } else {
+               
+               // if the method is not observer method then we just add the original method
+               // in set of methods of this class
+               newMethods.add(method);
+            }
+         }
+         
+         // Wrapper for annotated type
+         AnnotatedType<T> wrappedAnnotatedType = new AnnotatedType<T>() {
+            @Override
+            public <T extends Annotation> T getAnnotation(Class<T> arg0) {
+               return at.getAnnotation(arg0);
+            }
+
+            @Override
+            public Set<Annotation> getAnnotations() {
+               return at.getAnnotations();
+            }
+
+            @Override
+            public Type getBaseType() {
+               return at.getBaseType();
+            }
+
+            @Override
+            public Set<Type> getTypeClosure() {
+               return at.getTypeClosure();
+            }
+
+            @Override
+            public boolean isAnnotationPresent(Class<? extends Annotation> arg0) {
+               return at.isAnnotationPresent(arg0);
+            }
+
+            @Override
+            public Set<AnnotatedConstructor<T>> getConstructors() {
+               return at.getConstructors();
+            }
+
+            @Override
+            public Set<AnnotatedField<? super T>> getFields() {
+               return at.getFields();
+            }
+
+            @Override
+            public Class<T> getJavaClass() {
+               return at.getJavaClass();
+            }
+
+            @Override
+            public Set<AnnotatedMethod<? super T>> getMethods() {
+               // Only here we return the new set of methods which
+               // also include the modified observer method with @PortletEvent qualifier
+               return newMethods;
+            }
+         };
+         pat.setAnnotatedType(wrappedAnnotatedType);
+         
+      }
+      
+   }
+   
+   // Scan all @Observes methods in the app one at a time
+   <T, X> void processObserverMethod(@Observes ProcessObserverMethod<T, X> pom){
+      final ObserverMethod<T> observer = pom.getObserverMethod();
+      
+      
+      Set<Annotation> modifiedQualifiers = observer.getObservedQualifiers();
+      final Set<Annotation> originalQualifiers = new HashSet<Annotation>();
+      
+      for(Annotation qualifier : modifiedQualifiers){
+         if(!qualifier.annotationType().equals(PortletEvent.class)){
+            originalQualifiers.add(qualifier);
+         } /*else {
+            Annotation emptyEventAnnotation = new MyEmptyEvent();
+            originalQualifiers.add(emptyEventAnnotation);
+         }*/
+      }
+      
+      ObserverMethod<T> orginalObserverMethod = new ObserverMethod<T>() {
+
+         @Override
+         public Class<?> getBeanClass() {
+            return observer.getBeanClass();
+         }
+
+         @Override
+         public Type getObservedType() {
+            return observer.getObservedType();
+         }
+
+         @Override
+         public Set<Annotation> getObservedQualifiers() {
+            return originalQualifiers;
+         }
+
+         @Override
+         public Reception getReception() {
+            return observer.getReception();
+         }
+
+         @Override
+         public TransactionPhase getTransactionPhase() {
+            return observer.getTransactionPhase();
+         }
+
+         @Override
+         public void notify(T event) {
+            // Here we catch the original event
+            
+            // but do not let it reach the original observer
+            //observer.notify(event);
+            
+            // Code for firing all observers (including cross context) for this event
+            /*
+            boolean observerFound = false;
+            Set<Entry<AnnotatedField<?>, HashSet<ObserverMethod<?>>>> allEventsAndObservers = CDIEventsStore.event_observers.entrySet();
+            for(Entry<AnnotatedField<?>, HashSet<ObserverMethod<?>>> eventAndObservers : allEventsAndObservers){
+               HashSet<ObserverMethod<?>> eventObservers = eventAndObservers.getValue();
+               for(ObserverMethod<?> eventObserver : eventObservers){
+                  if(eventObserver.equals(observer)){
+                     for(ObserverMethod<?> allObserver : eventObservers){
+                        allObserver.notify(event);
+                     }
+                     observerFound=true;
+                     break;
+                  }
+               }
+               if(observerFound){
+                  break;
+               }
+            }
+            */
+            
+            // Try to save it here for later invocation
+            // We might also need to serialize the event here
+            /*
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            Writer out = new StringWriter();
+            @SuppressWarnings("rawtypes")
+            Class clazz = event.getClass();
+            try {
+               System.setProperty( "com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize", "true");
+               JAXBContext jc = JAXBContext.newInstance(clazz);
+               Marshaller marshaller = jc.createMarshaller();
+               JAXBElement<Serializable> element = new JAXBElement<Serializable>(new QName("http:eventexample.com/events",
+                     "portlet.api.event"), clazz, (Serializable) event);
+               marshaller.marshal(element, out);
+            } catch(Exception e) {
+               System.out.println("Error while serializing cdi event data "+e.toString());
+               e.printStackTrace();
+            } finally {
+               Thread.currentThread().setContextClassLoader(cl);
+               System.getProperties().remove("com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize");
+            }
+            CDIEventsStore.observerInvocation.put(observer, (Serializable) out.toString());
+            */
+            CDIEventsStore.observerInvocation.put(observer, event);
+            CDIEventsStore.eventStore.put(event, observer.getObservedQualifiers());
+            if(!CDIEventsStore.firedFromBeanManager){
+               CDIEventsStore.addEventToUniversalList(new PortletCDIEvent(observer.getObservedQualifiers(), (Serializable) event, observer.getBeanClass()));
+               CDIEventsStore.universalObserverList.add(observer);
+            }
+            //CDIEventsStore.universalEventList.add(new PortletCDIEvent(observer.getObservedQualifiers(), (Serializable) event));
+            //CDIEventsStore.printInvokedObservers();
+         }
+      };
+      
+      originalObserverMethods.add(orginalObserverMethod);
+      
+      // This is an alternate (more simpler) way of doing what we did above. 
+      // We could have let the original observers as it is 
+      // and made a new @PortletEvent qualified observer for each
+      // original observer. We wouldn't even need to touch the 
+      // original observers in ProcessAnnotatedType phase 
+      // BUT!!!
+      // The problem here is if we do it this way then how can we
+      // block the task being done by original observer??
+      /*
+      Set<Annotation> originalQualifiers = observer.getObservedQualifiers();
+      final Set<Annotation> modifiedQualifiers = new HashSet<Annotation>();
+      
+      for(Annotation qualifier : originalQualifiers){
+         modifiedQualifiers.add(qualifier);
+      }
+      
+      // Make the @PortletEvent qualifier
+      Annotation portletEventAnnotation = new MyPortletEvent();
+
+      // Add @PortletEvent annotation as last qualifier in the linked list
+      modifiedQualifiers.add(portletEventAnnotation);
+      
+      ObserverMethod<T> modifiedObserverMethod = new ObserverMethod<T>() {
+
+         @Override
+         public Class<?> getBeanClass() {
+            return observer.getBeanClass();
+         }
+
+         @Override
+         public Type getObservedType() {
+            return observer.getObservedType();
+         }
+
+         @Override
+         public Set<Annotation> getObservedQualifiers() {
+            return modifiedQualifiers;
+         }
+
+         @Override
+         public Reception getReception() {
+            return observer.getReception();
+         }
+
+         @Override
+         public TransactionPhase getTransactionPhase() {
+            return observer.getTransactionPhase();
+         }
+
+         @Override
+         public void notify(T event) {
+            System.out.println("Original event fired.");
+         }
+      };
+      
+      originalObserverMethods.add(modifiedObserverMethod);
+      */
+      
+      // Commenting out the code to match events and observers of different app
+      // Iterate through each event in event_observers map
+      
+      for (Map.Entry<AnnotatedField<?>, HashSet<ObserverMethod<?>>> entry : CDIEventsStore.event_observers.entrySet())
+      {
+         // See if this @Observes method belongs to this event
+         if(compareEventAndObserver(entry.getKey(), observer)){
+            // Add this @Observes method in HashSet of observers
+            // for this event
+            HashSet<ObserverMethod<?>> eventObservers = entry.getValue();
+            eventObservers.add(observer);
+         }
+      }
+      
+      
+      // Temporary code to match event and observers in the same app
+      // Iterate through each event in event_observers map
+      /*
+      for (AnnotatedField<?> field : fieldsInCurrentScope)
+      {
+         // See if this @Observes method belongs to this event
+         if(compareEventAndObserver(field, observer)){
+            // Add this @Observes method in HashSet of observers
+            // for this event
+            
+            HashSet<ObserverMethod<?>> eventObservers = CDIEventsStore.event_observers.get(field);
+            eventObservers.add(observer);
+         }
+      }
+      */
+   }
+
+   // Finish the scanning process
+   void afterBeanDiscovery(@Observes AfterBeanDiscovery abd) {
+      
+      for(ObserverMethod<?> observerMethod : originalObserverMethods){
+         abd.addObserverMethod(observerMethod);
+      }
+      
+      originalObserverMethods.clear();
+      
+      LOG.debug("Found these events and observers - ");
+      System.out.println("Found these events and observers - ");
+      for (Map.Entry<AnnotatedField<?>, HashSet<ObserverMethod<?>>> entry : CDIEventsStore.event_observers.entrySet())
+      {
+         System.out.println(entry.getKey().toString() + "/" + entry.getValue().toString());
+         LOG.debug(entry.getKey().toString() + "/" + entry.getValue().toString());
+      }
+      /*
+      for(AnnotatedField<?> field : fieldsInCurrentScope){
+         HashSet<ObserverMethod<?>> observerMethods = CDIEventsStore.event_observers.get(field);
+         for (ObserverMethod<?> observer : observerMethods) {
+            CrossContextObserver crossContextObserver = new CrossContextObserver();
+            crossContextObserver.setBeanClass(observer.getBeanClass());
+            crossContextObserver.setObservedQualifiers(observer.getObservedQualifiers());
+            crossContextObserver.setObservedType(observer.getObservedType());
+            crossContextObserver.setReception(observer.getReception());
+            abd.addObserverMethod(crossContextObserver);
+            break;
+         }
+      }
+      
+      */
+      fieldsInCurrentScope.clear();
+      System.out.println("Finished the scanning process");
+      LOG.debug("Finished the scanning process");
+   }
+   
+   // Method to compare event with an observer
+   // returns true if the observer belongs to the same event
+   // else false
+   private boolean compareEventAndObserver(AnnotatedField<?> event,
+         ObserverMethod<?> observer) {
+      
+      // Gets the qualifier from full event name
+      //String qualifierNameFromEvent = event.toString().split(" ")[2];
+      Annotation qualifierFromEvent = null;
+      for(Annotation eventAnnotation : event.getAnnotations()){
+         if (!eventAnnotation.annotationType().equals(EmptyEvent.class) && !eventAnnotation.annotationType().equals(Inject.class)){
+            qualifierFromEvent = eventAnnotation;
+         }
+      }
+      
+      // Initialize qualifier name from event to be empty
+      // in case there is none
+      //String qualifierFromEvent = "";
+      
+      // remove @ from qualifier name. This also checks whether 
+      // there is a qualifier for this event or not
+      /*if(qualifierNameFromEvent.contains("@")){
+         qualifierFromEvent = qualifierNameFromEvent.replace("@", "");
+      }*/
+      
+      // Initialize the qualifier name from observer 
+      // to be empty in case there is none 
+      Annotation qualifierFromObserver = null;
+      
+      // Get all qualifiers from @Observes method
+      Set<Annotation> qualifiers = observer.getObservedQualifiers();
+      
+      System.out.println("\n");
+      
+      // Get the qualifier name from @Observes method
+      for(Annotation annotation : qualifiers){
+         String observerType = annotation.toString();
+         System.out.println("Observer annotation: "+observerType);
+         String observerQualifier = observerType.substring(observerType.lastIndexOf(".")+1).replace("()", "");
+         
+         // Ignore @PortletEvent qualifier of observer while matching
+         // with qualifiers of event because we artificially added 
+         // @PortletEvent in observer
+         if(annotation.annotationType().equals(PortletEvent.class) || annotation.annotationType().equals(EmptyEvent.class)){
+            continue;
+         } else {
+            qualifierFromObserver = annotation;
+         }
+      }
+      
+      // Get the type of event value from event declaration
+      String eventValueType = event.getBaseType().toString();
+      
+      // Parse the type of event value
+      String eventValueTypeFromEvent = eventValueType.split("<")[1].replace(">", "");
+      
+      // Get the type of event value from @Observes method
+      String eventValueTypeFromObserver = observer.getObservedType().toString().split(" ")[1];    
+      
+      // Check if qualifiers and event value type matches
+      // for event declaration and observer declaration
+      
+      System.out.println("Qualifier from event: "+qualifierFromEvent);
+      System.out.println("Qualifier from observer: "+qualifierFromObserver);
+      System.out.println("Value type from event: "+eventValueTypeFromEvent);
+      System.out.println("Value type from observer: "+eventValueTypeFromObserver);
+      
+      if(eventValueTypeFromEvent.equals(eventValueTypeFromObserver)){
+         if(qualifierFromEvent == null && qualifierFromObserver == null){
+            return true;
+         } else if (qualifierFromEvent!=null && qualifierFromObserver!=null &&
+               qualifierFromEvent.equals(qualifierFromObserver)) {
+            return true;
+         } else {
+            return false;
+         }
+      } else {
+         return false;
+      }
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletEvent.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletEvent.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletEvent.java
new file mode 100644
index 0000000..4efd937
--- /dev/null
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletEvent.java
@@ -0,0 +1,29 @@
+package org.apache.pluto.container.bean.processor;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.METHOD;
+
+import javax.inject.Qualifier;
+
+/**
+ * An annotation that is used as a qualifier for events fired when
+ * a name is added.
+ * 
+ * @author nick
+ *
+ */
+/* 
+ * Just making a new annotation for our event.
+ * What we learn from here is not only implementations
+ * but also events can be specified as a Qualifier.
+ * To see the usage - See FormController class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+@Target({FIELD, METHOD, PARAMETER, TYPE})
+public @interface PortletEvent {}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
index e1aabc5..ea878e4 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
@@ -97,16 +97,24 @@ public abstract class StateAwareResponseImpl extends PortletResponseImpl
 
    public void setEvent(QName qname, Serializable value) {
       ArgumentUtility.validateNotNull("qname", qname);
+      Event event = null;
       
-      if (LOGGER.isTraceEnabled()) {
-         StringBuilder txt = new StringBuilder(128);
-         txt.append("QName: ").append(qname.toString());
-         txt.append(", value class: ").append((value == null) ? "null": value.getClass().getCanonicalName());
-         LOGGER.debug(txt.toString());
-      }
+      QName CDI_EVENT_QNAME = new QName("javax.portlet.cdi.event", "javax.portlet.cdi.event");
+      if(qname.equals(CDI_EVENT_QNAME)){
+         event = responseContext.getEventProvider()
+               .createCDIEvent(qname, value);
+      } else {
+         if (LOGGER.isTraceEnabled()) {
+            StringBuilder txt = new StringBuilder(128);
+            txt.append("QName: ").append(qname.toString());
+            txt.append(", value class: ").append((value == null) ? "null": value.getClass().getCanonicalName());
+            LOGGER.debug(txt.toString());
+         }
 
-      Event event = responseContext.getEventProvider()
-            .createEvent(qname, value);
+         event = responseContext.getEventProvider()
+               .createEvent(qname, value);
+      }
+      
       if (event != null) {
          responseContext.getEvents().add(event);
       }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-container/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/pluto-container/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index 0d229e2..bca7656 100644
--- a/pluto-container/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/pluto-container/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -1 +1,2 @@
-org.apache.pluto.container.bean.processor.PortletCDIExtension
\ No newline at end of file
+org.apache.pluto.container.bean.processor.PortletCDIExtension
+org.apache.pluto.container.bean.processor.PortletCDIEventExtension
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventCoordinationServiceImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventCoordinationServiceImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventCoordinationServiceImpl.java
index e54461d..f23a1d1 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventCoordinationServiceImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventCoordinationServiceImpl.java
@@ -24,8 +24,13 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
 
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.ObserverMethod;
+import javax.inject.Inject;
 import javax.portlet.Event;
 import javax.portlet.PortletException;
 import javax.servlet.ServletContext;
@@ -45,6 +50,9 @@ import org.apache.pluto.container.EventCoordinationService;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletContainerException;
 import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.bean.processor.AnnotatedConfigBean;
+import org.apache.pluto.container.bean.processor.CDIEventsStore;
+import org.apache.pluto.container.bean.processor.PortletCDIEvent;
 import org.apache.pluto.container.driver.PortletContextService;
 import org.apache.pluto.container.driver.PortletRegistryService;
 import org.apache.pluto.container.om.portlet.EventDefinition;
@@ -62,6 +70,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class EventCoordinationServiceImpl implements EventCoordinationService {
+   
    /** Logger. */
    private static final Logger          LOG           = LoggerFactory
                                                             .getLogger(EventCoordinationServiceImpl.class);
@@ -96,9 +105,12 @@ public class EventCoordinationServiceImpl implements EventCoordinationService {
 
       // ThreadGroup threadGroup = new ThreadGroup("FireEventThreads");
 
+      QName CDI_EVENT_QNAME = new QName("javax.portlet.cdi.event", "javax.portlet.cdi.event");
+      
       for (Event event : events) {
          List<String> portletNames = getAllPortletsRegisteredForEvent(event,
                driverConfig, containerServletContext, portalURL);
+         System.out.println(portletNames.size() + "portlets are responsible for "+event.getName()+" event");
 
          // Deliver events to all portlets in the portal
          // Collection<PortletWindowConfig> portlets =
@@ -150,6 +162,14 @@ public class EventCoordinationServiceImpl implements EventCoordinationService {
                }
             }
          }
+         for(PortletCDIEvent portletCDIEvent : CDIEventsStore.universalEventList){
+            if(event.getQName().equals(CDI_EVENT_QNAME) && event.getValue().equals(portletCDIEvent.getData())){
+               //System.out.println("Processed event "+ event.getValue().toString());
+               //System.out.println("processed both portlet event so removing event from universal event list.");
+               CDIEventsStore.universalEventList.remove(portletCDIEvent);
+               break;
+            }
+         }
       }
    }
 
@@ -158,15 +178,15 @@ public class EventCoordinationServiceImpl implements EventCoordinationService {
          PortletWindow portletWindow, Event event, HttpServletRequest request,
          HttpServletResponse response) {
       try {
+         
          Object value = event.getValue();
-
          XMLStreamReader xml = null;
          try {
             if (value instanceof String) {
                String in = (String) value;
                xml = XMLInputFactory.newInstance().createXMLStreamReader(
                      new StringReader(in));
-            }
+            } 
          } catch (XMLStreamException e1) {
             throw new IllegalStateException(e1);
          } catch (FactoryConfigurationError e1) {
@@ -175,38 +195,44 @@ public class EventCoordinationServiceImpl implements EventCoordinationService {
 
          if (xml != null) {
             // XMLStreamReader xml = (XMLStreamReader) event.getValue();
-
             // provider.getEventDefinition(event.getQName());
-            try {
-               // now test if object is jaxb
-               EventDefinition eventDefinitionDD = getEventDefintion(
-                     portletWindow, event.getQName());
-
-               ClassLoader loader = portletContextService
-                     .getClassLoader(portletWindow.getPortletDefinition()
-                           .getApplication().getName());
-               Class<? extends Serializable> clazz = loader.loadClass(
-                     eventDefinitionDD.getValueType()).asSubclass(
-                     Serializable.class);
-
-               JAXBContext jc = JAXBContext.newInstance(clazz);
-               Unmarshaller unmarshaller = jc.createUnmarshaller();
-
-               // unmarshaller.setEventHandler(new
-               // javax.xml.bind.helpers.DefaultValidationEventHandler());
-
-               JAXBElement result = unmarshaller.unmarshal(xml, clazz);
-
-               event = new EventImpl(event.getQName(),
-                     (Serializable) result.getValue());
-            } catch (JAXBException e) {
-               throw new IllegalStateException(e);
-            } catch (ClassCastException e) {
-               throw new IllegalStateException(e);
-            } catch (ClassNotFoundException e) {
-               throw new IllegalStateException(e);
-            } catch (PortletContainerException e) {
-               throw new IllegalStateException(e);
+            QName CDI_EVENT_QNAME = new QName("javax.portlet.cdi.event", "javax.portlet.cdi.event");
+            if(!event.getQName().equals(CDI_EVENT_QNAME)){
+               try {
+                  // now test if object is jaxb
+                  EventDefinition eventDefinitionDD = getEventDefintion(
+                        portletWindow, event.getQName());
+   
+                  ClassLoader loader = portletContextService
+                        .getClassLoader(portletWindow.getPortletDefinition()
+                              .getApplication().getName());
+                  Class<? extends Serializable> clazz = loader.loadClass(
+                        eventDefinitionDD.getValueType()).asSubclass(
+                        Serializable.class);
+   
+                  JAXBContext jc = JAXBContext.newInstance(clazz);
+                  Unmarshaller unmarshaller = jc.createUnmarshaller();
+   
+                  // unmarshaller.setEventHandler(new
+                  // javax.xml.bind.helpers.DefaultValidationEventHandler());
+   
+                  JAXBElement result = unmarshaller.unmarshal(xml, clazz);
+   
+                  event = new EventImpl(event.getQName(),
+                        (Serializable) result.getValue());
+               } catch (JAXBException e) {
+                  System.out.println(e.toString());
+                  throw new IllegalStateException(e);
+               } catch (ClassCastException e) {
+                  System.out.println(e.toString());
+                  throw new IllegalStateException(e);
+               } catch (ClassNotFoundException e) {
+                  System.out.println(e.toString());
+                  throw new IllegalStateException(e);
+               } catch (PortletContainerException e) {
+                  System.out.println(e.toString());
+                  throw new IllegalStateException(e);
+               } 
             }
          }
          container.doEvent(portletWindow, request, response, event);

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventProviderImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventProviderImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventProviderImpl.java
index 00f2a81..92fccc7 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventProviderImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/EventProviderImpl.java
@@ -103,6 +103,7 @@ public class EventProviderImpl implements EventProvider {
                @SuppressWarnings("rawtypes")
                Class clazz = value.getClass();
                try {
+                  System.setProperty( "com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize", "true");
                   Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
                   JAXBContext jc = JAXBContext.newInstance(clazz);
                   Marshaller marshaller = jc.createMarshaller();
@@ -110,12 +111,12 @@ public class EventProviderImpl implements EventProvider {
                   marshaller.marshal(element, out);
                } finally {
                   Thread.currentThread().setContextClassLoader(cl);
+                  System.getProperties().remove("com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize");
                }
                
                if (debug) {
                   LOG.debug("Resulting marshalled HashMap: \n" + out.toString());
                }
-               
                return new EventImpl(qname, out.toString());
             }
          } catch (JAXBException e) {
@@ -127,6 +128,30 @@ public class EventProviderImpl implements EventProvider {
       }
       return null;
    }
+   
+   // TODO: Document this
+   public Event createCDIEvent(QName qname, Serializable value) throws IllegalArgumentException {
+      
+      if (LOG.isDebugEnabled()) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("QName: ").append(qname.toString());
+         txt.append(", value class: ").append((value == null) ? "null": value.getClass().getCanonicalName());
+         LOG.debug(txt.toString());
+      }
+      
+      if (isDeclaredAsPublishingEvent(qname)) {
+         if (value != null && !isValueInstanceOfDefinedClass(qname, value)) {
+            throw new IllegalArgumentException("Payload class (" + value.getClass().getCanonicalName()
+                  + ") does not have the right class, check your defined event types in portlet.xml.");
+         }
+         try {
+           return new EventImpl(qname, value);
+         } catch (FactoryConfigurationError e) {
+            LOG.warn(e.getMessage(), e);
+         }
+      }
+      return null;
+   }
 
    private boolean isDeclaredAsPublishingEvent(QName qname) {
       String applicationId = PortletWindowConfig.parseContextPath(portletWindow.getId().getStringId());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/982077a9/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
index be3263b..4287dc8 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
@@ -164,6 +164,11 @@ public class PortletContextManager implements PortletRegistryService, PortletCon
         }
         return contextPath;
     }
+	
+	// TODO: Document this function
+	public void updatePortletConfig(DriverPortletContext portletContext, PortletDefinition portletDefinition){
+	   portletConfigs.put(portletContext.getApplicationName() + "/" + portletDefinition.getPortletName(), new DriverPortletConfigImpl(portletContext, portletDefinition));
+	}
 
     /**
      * @see org.apache.pluto.container.driver.PortletContextService#unregister(org.apache.pluto.container.driver.DriverPortletContext)