/** * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.portal.pc; import org.exoplatform.commons.utils.PropertyManager; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.portal.pc.aspects.PortletLifecyclePhaseInterceptor; import org.exoplatform.services.resources.ResourceBundleService; import org.gatein.common.logging.Logger; import org.gatein.common.logging.LoggerFactory; import org.gatein.pc.api.PortletInvoker; import org.gatein.pc.bridge.BridgeInterceptor; import org.gatein.pc.federation.FederatingPortletInvoker; import org.gatein.pc.federation.impl.FederatingPortletInvokerService; import org.gatein.pc.portlet.PortletInvokerInterceptor; import org.gatein.pc.portlet.aspects.CCPPInterceptor; import org.gatein.pc.portlet.aspects.ConsumerCacheInterceptor; import org.gatein.pc.portlet.aspects.ContextDispatcherInterceptor; import org.gatein.pc.portlet.aspects.EventPayloadInterceptor; import org.gatein.pc.portlet.aspects.PortletCustomizationInterceptor; import org.gatein.pc.portlet.aspects.ProducerCacheInterceptor; import org.gatein.pc.portlet.aspects.RequestAttributeConversationInterceptor; import org.gatein.pc.portlet.aspects.SecureTransportInterceptor; import org.gatein.pc.portlet.aspects.ValveInterceptor; import org.gatein.pc.portlet.container.ContainerPortletDispatcher; import org.gatein.pc.portlet.container.ContainerPortletInvoker; import org.gatein.pc.portlet.impl.deployment.DeploymentException; import org.gatein.pc.portlet.impl.deployment.PortletApplicationDeployer; import org.gatein.pc.portlet.impl.state.StateManagementPolicyService; import org.gatein.pc.portlet.impl.state.producer.PortletStatePersistenceManagerService; import org.gatein.pc.portlet.state.StateConverter; import org.gatein.pc.portlet.state.producer.ProducerPortletInvoker; import org.gatein.wci.ServletContainerFactory; import org.gatein.wci.WebAppEvent; import org.gatein.wci.WebAppLifeCycleEvent; import org.gatein.wci.WebAppListener; import org.picocontainer.Startable; /** * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> * @version $Revision$ */ public class ExoKernelIntegration implements Startable, WebAppListener { /** . */ protected PortletApplicationDeployer portletApplicationRegistry; /** Exo Context */ private final ExoContainer container; /** DO NOT REMOVE ME, OTHERWISE YOU'LL BREAK THINGS. */ @SuppressWarnings("unused") private final ResourceBundleService resourceBundleService; /** * Indicates whether or not the producerPortletInvoker has been registered from this class */ private boolean producerPortletInvokerSet; /** . */ private Logger log = LoggerFactory.getLogger(ExoKernelIntegration.class); /** * We enforce the dependency with the ResourceBundleService since it must be stared before the * <code>portletApplicationRegistry</code> * * @param context the exo container context * @param resourceBundleService the resource bundle service that is here for the sake of creating a dependency */ public ExoKernelIntegration(ExoContainerContext context, ResourceBundleService resourceBundleService) { this.container = context.getContainer(); this.resourceBundleService = resourceBundleService; } public void start() { // The portlet container invoker used by producer to dispatch to portlets ContainerPortletInvoker containerPortletInvoker = new ContainerPortletInvoker(); // The portlet application deployer portletApplicationRegistry = new ExoPortletApplicationDeployer(); portletApplicationRegistry.setContainerPortletInvoker(containerPortletInvoker); // activate schema validation for portlet.xml if needed String validation = PropertyManager.getProperty("gatein.portlet.validation"); boolean validated = validation == null || "true".equals(validation.trim().toLowerCase()); log.debug("portlet xml validation is " + (validated ? "enabled" : " disabled")); portletApplicationRegistry.setSchemaValidated(validated); // Container Stack ContainerPortletDispatcher portletContainerDispatcher = new ContainerPortletDispatcher(); FederatingPortletInvoker federatingPortletInvoker = new FederatingPortletInvokerService(); EventPayloadInterceptor eventPayloadInterceptor = new EventPayloadInterceptor(); eventPayloadInterceptor.setNext(portletContainerDispatcher); RequestAttributeConversationInterceptor requestAttributeConversationInterceptor = new RequestAttributeConversationInterceptor(); requestAttributeConversationInterceptor.setNext(eventPayloadInterceptor); CCPPInterceptor ccppInterceptor = new CCPPInterceptor(); ccppInterceptor.setNext(requestAttributeConversationInterceptor); BridgeInterceptor bridgepInterceptor = new BridgeInterceptor(); bridgepInterceptor.setNext(ccppInterceptor); ProducerCacheInterceptor producerCacheInterceptor = new ProducerCacheInterceptor(); producerCacheInterceptor.setNext(bridgepInterceptor); // SessionInvalidatorInterceptor is not needed as we have cross-context logout at WCI level // SessionInvalidatorInterceptor sessionInvalidatorInterceptor = new SessionInvalidatorInterceptor(); // sessionInvalidatorInterceptor.setNext(producerCacheInterceptor); ContextDispatcherInterceptor contextDispatcherInterceptor = new ContextDispatcherInterceptor(); contextDispatcherInterceptor.setNext(producerCacheInterceptor); PortletLifecyclePhaseInterceptor portletLifecyclePhaseInterceptor = new PortletLifecyclePhaseInterceptor(); portletLifecyclePhaseInterceptor.setNext(contextDispatcherInterceptor); SecureTransportInterceptor secureTransportInterceptor = new SecureTransportInterceptor(); secureTransportInterceptor.setNext(portletLifecyclePhaseInterceptor); ValveInterceptor valveInterceptor = new ValveInterceptor(); valveInterceptor.setPortletApplicationRegistry(portletApplicationRegistry); valveInterceptor.setNext(secureTransportInterceptor); // The portlet container invoker continued containerPortletInvoker.setNext(valveInterceptor); // register container invoker so that WSRP can use it, WSRP uses its own ProducerPortletInvoker container.registerComponentInstance(ContainerPortletInvoker.class, containerPortletInvoker); // The producer persistence manager PortletStatePersistenceManagerService producerPersistenceManager = new PortletStatePersistenceManagerService(); // The producer state management policy StateManagementPolicyService producerStateManagementPolicy = new StateManagementPolicyService(); producerStateManagementPolicy.setPersistLocally(false); // The producer state converter StateConverter producerStateConverter = new ExoStateConverter(); // The producer portlet invoker ProducerPortletInvoker producerPortletInvoker = new ProducerPortletInvoker(); producerPortletInvoker.setNext(containerPortletInvoker); producerPortletInvoker.setPersistenceManager(producerPersistenceManager); producerPortletInvoker.setStateManagementPolicy(producerStateManagementPolicy); producerPortletInvoker.setStateConverter(producerStateConverter); // register the producer portlet invoker if it hasn't been already if (!federatingPortletInvoker.isResolved(PortletInvoker.LOCAL_PORTLET_INVOKER_ID)) { federatingPortletInvoker.registerInvoker(PortletInvoker.LOCAL_PORTLET_INVOKER_ID, producerPortletInvoker); producerPortletInvokerSet = true; } // The consumer portlet invoker PortletCustomizationInterceptor portletCustomizationInterceptor = new PortletCustomizationInterceptor(); portletCustomizationInterceptor.setNext(federatingPortletInvoker); ConsumerCacheInterceptor consumerCacheInterceptor = new ConsumerCacheInterceptor(); consumerCacheInterceptor.setNext(portletCustomizationInterceptor); PortletInvokerInterceptor consumerPortletInvoker = new PortletInvokerInterceptor(); consumerPortletInvoker.setNext(consumerCacheInterceptor); // register federating portlet and consumerPortletInvoker invoker with container container.registerComponentInstance(PortletInvoker.class, consumerPortletInvoker); container.registerComponentInstance(FederatingPortletInvoker.class, federatingPortletInvoker); // ServletContainerFactory.getServletContainer().addWebAppListener(this); } public void stop() { ServletContainerFactory.getServletContainer().removeWebAppListener(this); if (!producerPortletInvokerSet || !PropertyManager.isDevelopping()) { // The current instance did not register the producerPortletInvoker so we have nothing to do or we are not in // developing mode return; } final ExoContainer topContainer = ExoContainerContext.getTopContainer(); FederatingPortletInvoker federatingPortletInvoker = (FederatingPortletInvoker) topContainer .getComponentInstanceOfType(FederatingPortletInvoker.class); if (federatingPortletInvoker != null && federatingPortletInvoker.isResolved(PortletInvoker.LOCAL_PORTLET_INVOKER_ID)) { // The current instance registered the producerPortletInvoker so we have to unregister it federatingPortletInvoker.unregisterInvoker(PortletInvoker.LOCAL_PORTLET_INVOKER_ID); } } public PortletApplicationDeployer getPortletApplicationRegistry() { return portletApplicationRegistry; } public void onEvent(WebAppEvent event) { if (event instanceof WebAppLifeCycleEvent) { WebAppLifeCycleEvent lifeCycleEvent = (WebAppLifeCycleEvent) event; int type = lifeCycleEvent.getType(); if (type == WebAppLifeCycleEvent.ADDED) { try { portletApplicationRegistry.add(lifeCycleEvent.getWebApp().getServletContext()); } catch (DeploymentException e) { log.error("Portlet deployment failed", e); } } else if (type == WebAppLifeCycleEvent.REMOVED) { portletApplicationRegistry.remove(lifeCycleEvent.getWebApp().getServletContext()); } } } }