diff --git a/cdi/injection/pom.xml b/cdi/injection/pom.xml new file mode 100644 index 000000000..d8a498fb1 --- /dev/null +++ b/cdi/injection/pom.xml @@ -0,0 +1,59 @@ + + + + + + org.gatein.cdi + gatein-cdi-parent + 3.6.0.Beta02-SNAPSHOT + + 4.0.0 + + gatein-cdi-injection + jar + GateIn CDI Portlet and Filter Injection + + + + javax.enterprise + cdi-api + provided + + + javax.portlet + portlet-api + provided + + + javax.servlet + javax.servlet-api + provided + + + org.gatein.pc + pc-portlet + + + + diff --git a/cdi/injection/src/main/java/org/gatein/cdi/CDIInjectionListener.java b/cdi/injection/src/main/java/org/gatein/cdi/CDIInjectionListener.java new file mode 100644 index 000000000..9a5825a6d --- /dev/null +++ b/cdi/injection/src/main/java/org/gatein/cdi/CDIInjectionListener.java @@ -0,0 +1,223 @@ +package org.gatein.cdi; + +import org.gatein.common.logging.Logger; +import org.gatein.common.logging.LoggerFactory; +import org.gatein.pc.portlet.container.PortletApplication; +import org.gatein.pc.portlet.container.managed.LifeCycleStatus; +import org.gatein.pc.portlet.container.managed.ManagedObject; +import org.gatein.pc.portlet.container.managed.ManagedObjectAddedEvent; +import org.gatein.pc.portlet.container.managed.ManagedObjectLifeCycleEvent; +import org.gatein.pc.portlet.container.managed.ManagedObjectRegistryEvent; +import org.gatein.pc.portlet.container.managed.ManagedObjectRegistryEventListener; +import org.gatein.pc.portlet.container.managed.ManagedPortletContainer; +import org.gatein.pc.portlet.container.managed.ManagedPortletFilter; +import org.gatein.pc.portlet.impl.jsr168.PortletFilterImpl; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionTarget; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.portlet.Portlet; +import javax.portlet.filter.ActionFilter; +import javax.portlet.filter.EventFilter; +import javax.portlet.filter.PortletFilter; +import javax.portlet.filter.RenderFilter; +import javax.portlet.filter.ResourceFilter; +import javax.servlet.ServletContext; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Ken Finnigan + */ +public class CDIInjectionListener implements ManagedObjectRegistryEventListener { + private final Logger log = LoggerFactory.getLogger(CDIInjectionListener.class); + + private static final String BEAN_MGR_ATTRIBUTE = "javax.enterprise.inject.spi.BeanManager"; + private static final String SERVLET_BEAN_MGR_ATTRIBUTE = "org.jboss.weld.environment.servlet.javax.enterprise.inject.spi.BeanManager"; + + private Map cdiMetaDataMap = new ConcurrentHashMap(); + + private List> filterClasses = new ArrayList>(); + + public CDIInjectionListener() { + filterClasses.add(ActionFilter.class); + filterClasses.add(EventFilter.class); + filterClasses.add(RenderFilter.class); + filterClasses.add(ResourceFilter.class); + } + + @Override + public void onEvent(ManagedObjectRegistryEvent event) { + + if (event instanceof ManagedObjectAddedEvent) { + // Track whether a portletContainer or portletFilter needs CDI injection + + ManagedObject managedObject = ((ManagedObjectAddedEvent) event).getManagedObject(); + + if (managedObject instanceof ManagedPortletContainer) { + + ManagedPortletContainer managedPortletContainer = (ManagedPortletContainer) managedObject; + PortletApplication portletApp = managedPortletContainer.getManagedPortletApplication().getPortletApplication(); + + createMetaData(managedPortletContainer.getId(), portletApp); + + } else if (managedObject instanceof ManagedPortletFilter) { + + ManagedPortletFilter managedPortletFilter = (ManagedPortletFilter) managedObject; + PortletApplication portletApp = managedPortletFilter.getManagedPortletApplication().getPortletApplication(); + + createMetaData(managedPortletFilter.getId(), portletApp); + } + + } else if (event instanceof ManagedObjectLifeCycleEvent) { + + ManagedObjectLifeCycleEvent lifeCycleEvent = (ManagedObjectLifeCycleEvent) event; + ManagedObject managedObject = lifeCycleEvent.getManagedObject(); + LifeCycleStatus status = lifeCycleEvent.getStatus(); + + if (managedObject instanceof ManagedPortletContainer) { + + if (LifeCycleStatus.STARTED == status || LifeCycleStatus.INITIALIZED == status) { + return; + } + + ManagedPortletContainer managedPortletContainer = (ManagedPortletContainer) managedObject; + CDIMetaData cdiMetaData = cdiMetaDataMap.get(managedPortletContainer.getId()); + + if (!cdiMetaData.cdiInjectionEnabled) { + return; + } + + Portlet portlet = managedPortletContainer.getPortletInstance(); + + if (null != portlet) { + if (null != portlet.getClass() && "javax.portlet.faces.GenericFacesPortlet".equals(portlet.getClass().getName())) { + // Only perform injection on non JSF portlets + cdiMetaData.cdiInjectionEnabled = false; + cdiMetaDataMap.put(cdiMetaData.key, cdiMetaData); + return; + } + + PortletApplication portletApp = managedPortletContainer.getManagedPortletApplication().getPortletApplication(); + + if (!cdiMetaData.injectionPerformed) { + performInjection(portlet, cdiMetaData, portletApp.getContext().getServletContext()); + } else { + performCleanup(portlet, cdiMetaData, portletApp.getContext().getServletContext()); + } + } + } else if (managedObject instanceof ManagedPortletFilter) { + + if (LifeCycleStatus.INITIALIZED == status) { + return; + } + + ManagedPortletFilter managedPortletFilter = (ManagedPortletFilter) managedObject; + CDIMetaData cdiMetaData = cdiMetaDataMap.get(managedPortletFilter.getId()); + + if (!cdiMetaData.cdiInjectionEnabled) { + return; + } + + PortletFilterImpl portletFilterImpl = (PortletFilterImpl) managedPortletFilter.getPortletFilter(); + PortletFilter portletFilterInstance; + + for (Class type : filterClasses) { + portletFilterInstance = (PortletFilter) portletFilterImpl.instance(type); + + if (null != portletFilterInstance) { + PortletApplication portletApp = managedPortletFilter.getManagedPortletApplication().getPortletApplication(); + + if (LifeCycleStatus.STARTED == status && !cdiMetaData.injectionPerformed) { + performInjection(portletFilterInstance, cdiMetaData, portletApp.getContext().getServletContext()); + } else if (LifeCycleStatus.CREATED == status && cdiMetaData.injectionPerformed) { + performCleanup(portletFilterInstance, cdiMetaData, portletApp.getContext().getServletContext()); + } + + break; + } + } + } + } + } + + private void createMetaData(String id, PortletApplication portletApp) { + CDIMetaData metaData = new CDIMetaData(); + metaData.key = id; + + if (null != portletApp.getContext().getServletContext().getAttribute(BEAN_MGR_ATTRIBUTE)) { + metaData.cdiInjectionEnabled = true; + } else { + Object beanManager = portletApp.getContext().getServletContext().getAttribute(SERVLET_BEAN_MGR_ATTRIBUTE); + if (null != beanManager) { + metaData.cdiInjectionEnabled = true; + portletApp.getContext().getServletContext().setAttribute(BEAN_MGR_ATTRIBUTE, beanManager); + } + } + + cdiMetaDataMap.put(id, metaData); + } + + private void performInjection(Object instance, CDIMetaData metaData, ServletContext servletContext) { + // Perform CDI injection + Object beanManagerObject = servletContext.getAttribute(BEAN_MGR_ATTRIBUTE); + + if (null == beanManagerObject) { + log.error("Unable to retrieve BeanManager from ServletContext"); + return; + } + + ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(servletContext.getClassLoader()); + + BeanManager beanManager = (BeanManager) beanManagerObject; + CreationalContext creationalContext = beanManager.createCreationalContext(null); + InjectionTarget injectionTarget = beanManager.createInjectionTarget(beanManager.createAnnotatedType(instance.getClass())); + injectionTarget.inject(instance, creationalContext); + + Thread.currentThread().setContextClassLoader(oldCL); + + metaData.injectionPerformed = true; + metaData.creationalContext = creationalContext; + metaData.injectionTarget = injectionTarget; + + cdiMetaDataMap.put(metaData.key, metaData); + } + + private void performCleanup(Object instance, CDIMetaData metaData, ServletContext servletContext) { + // Perform CDI cleanup + InjectionTarget injectionTarget = metaData.injectionTarget; + CreationalContext creationalContext = metaData.creationalContext; + + ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(servletContext.getClassLoader()); + + if (null != injectionTarget) { + injectionTarget.dispose(instance); + metaData.injectionTarget = null; + } + + if (null != creationalContext) { + creationalContext.release(); + metaData.creationalContext = null; + } + + Thread.currentThread().setContextClassLoader(oldCL); + + metaData.injectionPerformed = false; + cdiMetaDataMap.put(metaData.key, metaData); + } + + private class CDIMetaData { + private String key; + private boolean cdiInjectionEnabled = false; + private boolean injectionPerformed = false; + private InjectionTarget injectionTarget; + private CreationalContext creationalContext; + } +} diff --git a/cdi/pom.xml b/cdi/pom.xml new file mode 100644 index 000000000..949e4ce82 --- /dev/null +++ b/cdi/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + GateIn CDI Enhancements + + org.gatein.cdi + gatein-cdi-parent + 3.6.0.Beta02-SNAPSHOT + + pom + + + org.gatein.portal + exo.portal.parent + 3.6.0.Beta02-SNAPSHOT + + + GateIn CDI Enhancements parent + + + injection + + diff --git a/component/pc/pom.xml b/component/pc/pom.xml index e8a87764c..9016089a5 100644 --- a/component/pc/pom.xml +++ b/component/pc/pom.xml @@ -1,17 +1,17 @@ diff --git a/packaging/jboss-as7/modules/src/main/resources/modules/org/gatein/lib/main/module.xml b/packaging/jboss-as7/modules/src/main/resources/modules/org/gatein/lib/main/module.xml index 8cd5060f5..0836853b6 100644 --- a/packaging/jboss-as7/modules/src/main/resources/modules/org/gatein/lib/main/module.xml +++ b/packaging/jboss-as7/modules/src/main/resources/modules/org/gatein/lib/main/module.xml @@ -77,6 +77,7 @@ + diff --git a/packaging/tomcat/pkg/pom.xml b/packaging/tomcat/pkg/pom.xml index 3380066de..6a90cf3da 100644 --- a/packaging/tomcat/pkg/pom.xml +++ b/packaging/tomcat/pkg/pom.xml @@ -364,6 +364,16 @@ jboss-dmr + + + org.gatein.cdi + gatein-cdi-injection + + + javax.enterprise + cdi-api + + org.staxnav diff --git a/pom.xml b/pom.xml index e5db22094..4e873194a 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ 5.1.7.Final 1.3.15.GA + 1.0-SP4 4.1.2 @@ -132,6 +133,7 @@ starter wsrp-integration mobile-integration + cdi packaging testsuite @@ -1074,6 +1076,13 @@ ${version.picketlink.fed} + + + org.gatein.cdi + gatein-cdi-injection + ${project.version} + + org.infinispan @@ -1105,6 +1114,11 @@ httpcore ${version.org.apache.httpcomponents.httpcore} + + javax.enterprise + cdi-api + ${version.cdi.spec} +