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)