Package org.exoplatform.webui.application.portlet

Source Code of org.exoplatform.webui.application.portlet.PortletApplication

/**
* 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.webui.application.portlet;

import org.exoplatform.commons.utils.PortalPrinter;
import org.exoplatform.commons.utils.Safe;
import org.exoplatform.resolver.ApplicationResourceResolver;
import org.exoplatform.resolver.PortletResourceResolver;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.web.application.ApplicationLifecycle;
import org.exoplatform.web.application.RequestContext;
import org.exoplatform.webui.application.WebuiApplication;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.core.UIApplication;
import org.exoplatform.webui.core.UIComponent;
import org.exoplatform.webui.core.UIPortletApplication;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.Event.Phase;

import java.io.IOException;
import java.io.Writer;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

/**
* May 26, 2006
*
* A portlet application. Every call made to a portlet deployed in eXo PC - and using eXo web framework -
* is going through this class
*/
public class PortletApplication extends WebuiApplication
{

   protected static Log log = ExoLogger.getLogger("portlet:PortletApplication");

   public final static String PORTLET_EVENT_VALUE = "portletEventValue";

   /**
    * The configuration parameter of this portlet
    */
   private PortletConfig portletConfig_;

   /**
    * The id of this portlet
    */
   private String applicationId_;

   /**
    *  This constructor has 2 purposes:
    *     1) recreate the application id
    *     2) configure the resource resolver to look in different UIR scheme (here app: and par:)
    */
   public PortletApplication(PortletConfig config) throws Exception
   {
      portletConfig_ = config;
      PortletContext pcontext = config.getPortletContext();
      String contextName = pcontext.getPortletContextName();
      applicationId_ = contextName + "/" + config.getPortletName();

      ApplicationResourceResolver resolver = new ApplicationResourceResolver();
      resolver.addResourceResolver(new PortletResourceResolver(pcontext, "app:"));
      resolver.addResourceResolver(new PortletResourceResolver(pcontext, "par:"));
      setResourceResolver(resolver);
   }

   public String getApplicationId()
   {
      return applicationId_;
   }

   public String getApplicationName()
   {
      return portletConfig_.getPortletName();
   }

   public String getApplicationGroup()
   {
      return portletConfig_.getPortletContext().getPortletContextName();
   }

   @Override
   public String getApplicationType()
   {
      return JSR168_APPLICATION_TYPE;
   }

   public ResourceBundle getResourceBundle(Locale locale) throws Exception
   {
      return portletConfig_.getResourceBundle(locale);
   }

   @SuppressWarnings("unused")
   public ResourceBundle getOwnerResourceBundle(String username, Locale locale) throws Exception
   {
      return null;
   }

   public String getApplicationInitParam(String name)
   {
      return portletConfig_.getInitParameter(name);
   }

   /**
    * The processAction() method is the one modelled according to the Portlet API specification
    *
    * The process is quite simple and here are te different steps done in the method:
    *
    * 1) The current instance of the WebuiRequestContext (stored in a ThreadLocal in the class) is referenced
    * 2) A new request context of type PortletRequestContext (which extends the class WebuiRequestContext) is
    *    created as a child of the current context instance
    * 3) The new context is place inside the ThreadLocal and hence overides its parent one there,
    *    only for the portlet request lifeciclye
    * 4) The method onStartRequest() is called in all the ApplicationLifecycle objects referenced in the webui
    *    configuration XML file
    * 5) The StateManager object (in case of portlet it is an object of type ParentAppStateManager) is used to get the RootComponent
    *    also referenced in the XML configuration file
    * 6) The methods processDecode(UIApplication, WebuiRequestContext) and processAction(UIApplication, WebuiRequestContext)
    *     are then called
    * 7) Finally, a flag, to tell that the processAction phase was done, in the context is set to true and the parent
    *    context is restored in the Threadlocal
    */
   public void processAction(ActionRequest req, ActionResponse res) throws Exception
   {
      WebuiRequestContext parentAppRequestContext = WebuiRequestContext.getCurrentInstance();
      PortletRequestContext context = createRequestContext(req, res, parentAppRequestContext);
      WebuiRequestContext.setCurrentInstance(context);
      try
      {
         for (ApplicationLifecycle<RequestContext> lifecycle : getApplicationLifecycle())
         {
            lifecycle.onStartRequest(this, context);
         }
         UIApplication uiApp = getStateManager().restoreUIRootComponent(context);
         context.setUIApplication(uiApp);
         uiApp.processDecode(context);
         if (!context.isResponseComplete() && !context.getProcessRender())
         {
            uiApp.processAction(context);
         }
      }
      finally
      {
         context.setProcessAction(true);
         WebuiRequestContext.setCurrentInstance(parentAppRequestContext);
      }
   }

   /**
    * This method is called when a JSR 286 event is targeting the current portlet.
    *
    * The event is transformed in a WebUI event using the convention that the 286
    * event name will target the EventNameActionListener class of one of the UIComponent in
    * the portlet uicomponent tree
    *
    * The event value is passed as an attribute of the PortletRequestContext
    */
   public void processEvent(EventRequest req, EventResponse res) throws Exception
   {
      WebuiRequestContext parentAppRequestContext = WebuiRequestContext.getCurrentInstance();
      PortletRequestContext context = createRequestContext(req, res, parentAppRequestContext);
      WebuiRequestContext.setCurrentInstance(context);
      try
      {
         for (ApplicationLifecycle<RequestContext> lifecycle : getApplicationLifecycle())
         {
            lifecycle.onStartRequest(this, context);
         }
         UIApplication uiApp = getStateManager().restoreUIRootComponent(context);
         context.setUIApplication(uiApp);
         javax.portlet.Event portletEvent = req.getEvent();
         context.setAttribute(PORTLET_EVENT_VALUE, portletEvent.getValue());
         Event<UIComponent> uiEvent = uiApp.createEvent(portletEvent.getName(), Phase.PROCESS, context);
         uiEvent.broadcast();
      }
      finally
      {
         WebuiRequestContext.setCurrentInstance(parentAppRequestContext);
      }
   }

   /**
    * The render method business logic is quite similar to the processAction() one.
    *
    * 1) A PortletRequestContext object is created (or extracted from the cache if it already exists)
    *    and initialized
    * 2) The PortletRequestContext replaces the parent one in the WebuiRequestContext ThreadLocal object
    * 3) If the portal has already called the portlet processAction() then the call to all onStartRequest of
    *    the ApplicationLifecycle has already been made, otherwise we call them
    * 4) The ParentStateManager is also used to get the UIApplication, as we have seen it delegates the call
    *    to the PortalStateManager which caches the UI component root associated with the current application
    * 5) the processRender() method of the UIPortletApplucaton is called
    * 6) Finally, the method onEndRequest() is called on every ApplicationLifecycle referenced in the portlet
    *    configuration XML file and the parent WebuiRequestContext is restored
    *   
    */
   public void render(RenderRequest req, RenderResponse res) throws Exception
   {
      WebuiRequestContext parentAppRequestContext = WebuiRequestContext.getCurrentInstance();
      PortletRequestContext context = createRequestContext(req, res, parentAppRequestContext);
      WebuiRequestContext.setCurrentInstance(context);
      try
      {
         if (!context.hasProcessAction())
         {
            for (ApplicationLifecycle<RequestContext> lifecycle : getApplicationLifecycle())
            {
               lifecycle.onStartRequest(this, context);
            }
         }
         UIApplication uiApp = getStateManager().restoreUIRootComponent(context);
         context.setUIApplication(uiApp);
         if (!context.isResponseComplete())
         {
            UIPortletApplication uiPortletApp = (UIPortletApplication)uiApp;
            uiPortletApp.processRender(this, context);
         }
         uiApp.setLastAccessApplication(System.currentTimeMillis());
      }
      finally
      {

         // Close the writer
         Safe.close(context.getWriter());

         //
         try
         {
            for (ApplicationLifecycle<RequestContext> lifecycle : getApplicationLifecycle())
            {
               lifecycle.onEndRequest(this, context);
            }
         }
         catch (Exception exception)
         {
            log.error("Error while trying to call onEndRequest of the portlet ApplicationLifecycle", exception);
         }
         WebuiRequestContext.setCurrentInstance(parentAppRequestContext);
      }
   }

   /**
    * In this method we try to get the PortletRequestContext object from the attribute map of the parent
    * WebuiRequestContext.
    *
    * If it is not cached then we create a new instance, if it is cached then we init it with the correct
    * writer, request and response objects
    *
    * We finally cache it in the parent attribute map
    *
    */
   private PortletRequestContext createRequestContext(PortletRequest req, PortletResponse res,
      WebuiRequestContext parentAppRequestContext) throws IOException
   {
      String attributeName = getApplicationId() + "$PortletRequest";
      PortletRequestContext context = (PortletRequestContext)parentAppRequestContext.getAttribute(attributeName);
      PortalPrinter w = null;
      if (res instanceof RenderResponse)
      {
         RenderResponse renderRes = (RenderResponse)res;
         renderRes.setContentType("text/html; charset=UTF-8");
         w = new PortalPrinter(renderRes.getPortletOutputStream(), true, 0);
      }
      if (context != null)
      {
         context.init(w, req, res);
      }
      else
      {
         context = new PortletRequestContext(this, w, req, res);
         parentAppRequestContext.setAttribute(attributeName, context);
      }
      context.setParentAppRequestContext(parentAppRequestContext);
      return context;
   }

}
TOP

Related Classes of org.exoplatform.webui.application.portlet.PortletApplication

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.