Portal Lifecycle
This chapter describes the portal lifecycles from the application server launch to its stop as well as how requests are handledApplication Server start and stop
An eXo Portal instance is simply a web application deployed as a WAR in an application server. Each portlet is also part of an enhanced WAR that we call a portlet application. Hence, the portal web.xml file is the main entry point to grab information about how does the portal starts. The web.xml file contains several information such as a listener, a servlet as well as some security information.The Listener
In the web.xml we can find servlet listener:<!-- ================================================================== --> <!-- LISTENER --> <!-- ================================================================== --> <listener> <listener-class>org.exoplatform.portal.application.PortalSessionListener</listener-class> </listener>
public class PortalSessionListener implements HttpSessionListener
/** * This method is called when a HTTP session of a Portal instance is destroyed. * By default the session time is 30 minutes. * * In this method, we: * 1) first get the portal instance name from where the session is removed. * 2) Get the correct instance object from the Root container * 3) Put the portal instance in the Portal ThreadLocal * 4) Get the main entry point (WebAppController) from the current portal container * 5) Extract from the WebAppController the PortalApplication object which is the entry point to * the StateManager object * 6) Expire the portal session stored in the StateManager * 7) Finally, removes the WindowInfos object from the WindowInfosContainer container * 8) Flush the threadlocal for the PortalContainer * */ public void sessionDestroyed(HttpSessionEvent event) { try { String portalContainerName = event.getSession().getServletContext().getServletContextName() ; log.warn("Destroy session from " + portalContainerName + " portal"); RootContainer rootContainer = RootContainer.getInstance() ; PortalContainer portalContainer = rootContainer.getPortalContainer(portalContainerName) ; PortalContainer.setInstance(portalContainer); WebAppController controller = (WebAppController)portalContainer.getComponentInstanceOfType(WebAppController.class) ; PortalApplication portalApp = controller.getApplication(PortalApplication.PORTAL_APPLICATION_ID) ; portalApp.getStateManager().expire(event.getSession().getId(), portalApp) ; WindowInfosContainer.removeInstance(portalContainer, event.getSession().getId()); } catch(Exception ex) { log.error("Error while destroying a portal session",ex); } finally { PortalContainer.setInstance(null) ; } }
The Servlet
The servlet is the main entry point for incoming request, it also includes some interesting init code when the portal is launched. Here is its definition in the web.xml file<!-- ================================================================== --> <!-- SERVLET --> <!-- ================================================================== --> <servlet> <servlet-name>portal</servlet-name> <servlet-class>org.exoplatform.portal.application.PortalController</servlet-class> <init-param> <param-name>webui.configuration</param-name> <param-value>app:/WEB-INF/webui-configuration.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
public class PortalController extends HttpServlet { /** * The init() method is used to prepare the portal to receive requests. * * 1) Create the PortalContainer and store it inside the ThreadLocal object. The PortalContainer is * a child of the RootContainer * 2) Get the WebAppController component from the container * 3) Create a new PortalApplication, init it with the ServletConfig object (which contains init params) * 4) Register that PortalApplication inside WebAppController * 5) Create a new PortalRequestHandler object and register it in the WebAppController * 6) Release the PortalContainer ThreadLocal */ @SuppressWarnings("unchecked") public void init(ServletConfig config) throws ServletException { super.init(config) ; try { RootContainer rootContainer = RootContainer.getInstance() ; PortalContainer portalContainer = rootContainer.getPortalContainer(config.getServletContext().getServletContextName()) ; portalContainer = rootContainer.createPortalContainer(config.getServletContext()) ; PortalContainer.setInstance(portalContainer) ; WebAppController controller = (WebAppController)portalContainer.getComponentInstanceOfType(WebAppController.class) ; PortalApplication application = new PortalApplication(config); application.onInit() ; controller.addApplication(application) ; controller.register(new PortalRequestHandler()) ; PortalContainer.setInstance(null) ; } catch (Throwable t){ throw new ServletException(t) ; } }
/** * The PortalApplication class is an implementation of the WebuiApplication abstract class * which defines the type of application that can be deployed in our framework (that includes * portal, portlets, widgets...) * * This class is a wrapper of all portal information such as ResourceBundle for i18n, the current * ExoContainer in use as well as the init parameters defined along with the servlet web.xml */ public class PortalApplication extends WebuiApplication {
/** * The constructor references resource resolvers that allows the ApplicationResourceResolver to * extract files from different locations such as the current war or external one such as the resource * one where several static files are shared among all portal instances. * * * @param config, the servlet config that contains init params such as the path location of * the XML configuration file for the WebUI framework */ public PortalApplication(ServletConfig config) throws Exception { sconfig_ = config ; ApplicationResourceResolver resolver = new ApplicationResourceResolver() ; resolver.addResourceResolver(new ServletResourceResolver(config.getServletContext(), "war:")) ; resolver.addResourceResolver(new ServletResourceResolver(config.getServletContext(), "app:")) ; resolver.addResourceResolver(new ServletResourceResolver(config.getServletContext(), "system:")) ; resolver.addResourceResolver(new ServletResourceResolver(config.getServletContext().getContext("/eXoResources"), "resources:")) ; setResourceResolver(resolver) ; }
/** * This method first calls the super.onInit() of the WebuiApplication. That super method parse the XML * file and stores its content in the ConfigurationManager object. It also set up he StateManager and * init the application lifecycle phases. * * Then we get all the properties file that will be used to create ResourceBundles */ public void onInit() throws Exception { super.onInit() ; applicationResourceBundleNames_ = getConfigurationManager().getApplication().getInitParams(). getParam("application.resource.bundle").getValue().split(","); for(int i = 0; i < applicationResourceBundleNames_.length; i++) { applicationResourceBundleNames_[i] = applicationResourceBundleNames_[i].trim() ; } }
<webui-configuration> <application> <init-params> <param> <name>application.resource.bundle</name> <value>locale.portal.expression, locale.portal.services, locale.portal.webui</value> </param> </init-params> <ui-component-root>org.exoplatform.portal.webui.workspace.UIPortalApplication</ui-component-root> <state-manager>org.exoplatform.portal.application.PortalStateManager</state-manager> <application-lifecycle-listeners> <listener>org.exoplatform.portal.application.PortalApplicationLifecycle</listener> <listener>org.exoplatform.webui.application.MonitorApplicationLifecycle</listener> </application-lifecycle-listeners> <events> <event> <event-name>portal.application.lifecycle.event</event-name> <listener>org.exoplatform.webui.event.ConsoleEventMonitorListener</listener> </event> <event> <event-name>portal.execution.lifecycle.event</event-name> <listener>org.exoplatform.webui.event.ConsoleEventMonitorListener</listener> </event> </events> </application> </webui-configuration>
The ui-component-root
Here it is the class org.exoplatform.portal.webui.workspace.UIPortalApplication which is a class that extends the UIApplication and hence is a sibling of UIPortletApplication (used by any eXo Portlets as the Parent class to build the portlet component tree). The UIPortalApplication is responsible to build its subtree - at request time) according to some configuration parameters. If all components are displayed it is composed of 3 UI components:- UIControlWorkSpace : the left expandable column that can contains widgets containers and the start menu
- UIWorkingWorkSpace: the right part that can display the normal or webos portal layouts
- UIPopupWindow: a popup window that display or not
/** * The constructor of this class is used to build the tree of UI components that will be aggregated * in the portal page. * * 1) The component is stored in the current PortalRequestContext ThreadLocal * 2) The configuration for the portal associated with the current user request is extracted from the * PortalRequestContext * 3) Then according to the context path, either a public or private portal is initiated. Usually a public * portal does not contain the left column and only the private one has it. * 4) The skin to use is setup * 5) Finally, the current component is associated with the current portal owner * * @param initParams * @throws Exception */ @SuppressWarnings("hiding") public UIPortalApplication(InitParams initParams) throws Exception { PortalRequestContext context = PortalRequestContext.getCurrentInstance() ; context.setUIApplication(this); userPortalConfig_ = (UserPortalConfig)context.getAttribute(UserPortalConfig.class); if(userPortalConfig_ == null) throw new Exception("Can't load user portal config"); if(context.getAccessPath() == PortalRequestContext.PUBLIC_ACCESS) { if(log.isDebugEnabled()) log.debug("Build a public portal"); initPublicPortal(context, initParams) ; } else { if(log.isDebugEnabled()) log.debug("Build a private portal"); initPrivatePortal(context) ; } String currentSkin = userPortalConfig_.getPortalConfig().getSkin(); if(currentSkin != null && currentSkin.trim().length() > 0) skin_ = currentSkin; setOwner(context.getPortalOwner()); }
The StateManager
The StateManager here is the org.exoplatform.portal.application.PortalStateManager which extends the StateManager abstract class.abstract public class StateManager { abstract public UIApplication restoreUIRootComponent(WebuiRequestContext context) throws Exception ; abstract public void storeUIRootComponent(WebuiRequestContext context) throws Exception ; abstract public void expire(String sessionId, WebuiApplication app) throws Exception ; }
The application-lifecycle-listeners
There are 2 lifecycle listeners in the Portal, one for the real business logic (PortalApplicationLifecycle), the other one for some monitoring issues. They both implements the interface ApplicationLifecyclepublic interface ApplicationLifecycle<E extends RequestContext> { public void onInit(Application app) throws Exception ; public void onStartRequest(Application app, E context) throws Exception ; public void onEndRequest(Application app, E context) throws Exception ; public void onDestroy(Application app) throws Exception ; }
Handling Requests
Once started and fully configured, the portal application WAR can handle HTTP requests. The entry point is for sure the PortalController Servlet we have already seen in the current chapter and defined in the web.xml of the portal context./** * This method simply delegates the incoming call to the WebAppController stored in the Portal Container object */ public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { ServletConfig config = getServletConfig() ; RootContainer rootContainer = RootContainer.getInstance() ; PortalContainer portalContainer = rootContainer.getPortalContainer(config.getServletContext().getServletContextName()) ; PortalContainer.setInstance(portalContainer) ; WebAppController controller = (WebAppController)portalContainer.getComponentInstanceOfType(WebAppController.class) ; controller.service(req, res) ; PortalContainer.setInstance(null) ; } catch (Throwable t){ throw new ServletException(t) ; } }
/** * The WebAppControler along with the PortalRequestHandler defined in the init() method of the * PortalController servlet (controller.register(new PortalRequestHandler())) also add the * CommandHandler object * * @throws Exception */ public WebAppController() throws Exception { applications_ = new HashMap<String, Application>() ; attributes_ = new HashMap<String, Object>() ; handlers_ = new HashMap<String, WebRequestHandler>() ; register(new CommandHandler()) ; }
/** * This is the first method - in the eXo web framework - reached by incoming HTTP request, it acts like a * servlet service() method * * According to the servlet path used the correct handler is selected and then executed. * * The event "exo.application.portal.start-http-request" and "exo.application.portal.end-http-request" are also sent * through the ListenerService and several listeners may listen to it. * * Finally a WindowsInfosContainer object using a ThreadLocal (from the portlet-container product) is created */ public void service(HttpServletRequest req, HttpServletResponse res) throws Exception { WebRequestHandler handler = handlers_.get(req.getServletPath()) ; if(log.isDebugEnabled()) { log.debug("Servlet Path: " + req.getServletPath()); log.debug("Handler used for this path: " + handler); } if(handler != null) { PortalContainer portalContainer = PortalContainer.getInstance() ; List<ComponentRequestLifecycle> components = portalContainer.getComponentInstancesOfType(ComponentRequestLifecycle.class) ; ListenerService lservice = (ListenerService) portalContainer.getComponentInstanceOfType(ListenerService.class) ; lservice.broadcast("exo.application.portal.start-http-request", this, req) ; for(ComponentRequestLifecycle component : components) { component.startRequest(portalContainer); } WindowInfosContainer.createInstance(portalContainer, req.getSession().getId(), req.getRemoteUser()); handler.execute(this, req, res) ; for(ComponentRequestLifecycle component : components) { component.endRequest(portalContainer); } lservice.broadcast("exo.application.portal.end-http-request", this, req) ; } }
/** * Created by The eXo Platform SAS * Mar 21, 2007 * * Abstract calss that one must implement if it want to provide a dedicated handler for a custom servlet path * * In case of portal the path is /portal but you could return your own from the getPath() method and hence the * WebAppController would use your own handler * * The execute method is to be overideen and the buisness logic should be handled here */ abstract public class WebRequestHandler { public void onInit(WebAppController controller) throws Exception{ } abstract public String[] getPath() ; abstract public void execute(WebAppController app, HttpServletRequest req, HttpServletResponse res) throws Exception ; public void onDestroy(WebAppController controler) throws Exception { } }
/** * Created by The eXo Platform SAS * Dec 9, 2006 * * This class handle the request that target the portal paths /public and /private * */ public class PortalRequestHandler extends WebRequestHandler { protected static Log log = ExoLogger.getLogger("portal:PortalRequestHandler"); static String[] PATHS = {"/public", "/private"} ; public String[] getPath() { return PATHS ; } /** * This method will handle incoming portal request. It gets a reference to the WebAppController * * Here are the steps done in the method: * * 1) set the header Cache-Control to no-cache * 2) Get the PortalApplication reference from the controller * 3) Create a PortalRequestContext object that is a convenient wrapper on all the request information * 4) Set that context in a ThreadLocal to easily access it * 5) Get the collection of ApplicationLifecycle referenced in the PortalApplication and defined in the * webui-configuration.xml of the portal application * 6) Call onStartRequest() on each ApplicationLifecycle object * 7) Get the StateManager object from the PortalApplication (also referenced in the XML file) * 8) Use the StateManager to get a reference on the root UI component: UIApplication; the method used is * restoreUIRootComponent(context) * 9) If the UI component is not the current one in used in the PortalContextRequest, then replace it * 10) Process decode on the PortalApplication * 11) Process Action on the PortalApplication * 12) Process Render on the UIApplication UI component * 11) call onEndRequest on all the ApplicationLifecycle * 12) Release the context from the thread * */ @SuppressWarnings("unchecked") public void execute(WebAppController controller, HttpServletRequest req, HttpServletResponse res) throws Exception { log.debug("Session ID = " + req.getSession().getId()); res.setHeader("Cache-Control", "no-cache"); PortalApplication app = controller.getApplication(PortalApplication.PORTAL_APPLICATION_ID) ; WebuiRequestContext context = new PortalRequestContext(app, req, res) ; ; WebuiRequestContext.setCurrentInstance(context) ; List<ApplicationLifecycle> lifecycles = app.getApplicationLifecycle(); try { for(ApplicationLifecycle lifecycle : lifecycles) lifecycle.onStartRequest(app, context) ; UIApplication uiApp = app.getStateManager().restoreUIRootComponent(context) ; if(context.getUIApplication() != uiApp) context.setUIApplication(uiApp) ; if(uiApp != null) app.processDecode(uiApp, context) ; if(!context.isResponseComplete() && !context.getProcessRender()) { app.processAction(uiApp, context) ; } if(!context.isResponseComplete()) uiApp.processRender(context) ; if(uiApp != null) uiApp.setLastAccessApplication(System.currentTimeMillis()) ; } catch(Exception ex){ log.error("Error while handling request",ex); } finally { try { for(ApplicationLifecycle lifecycle : lifecycles) lifecycle.onEndRequest(app, context) ; } catch (Exception exception){ log.error("Error while ending request on all ApplicationLifecycle",exception); } WebuiRequestContext.setCurrentInstance(null) ; } }
/** * Created by The eXo Platform SAS * May 7, 2006 * * This abstract class is a wrapper on top of the request information such as the Locale in use, * the application (for instance PortalApplication, PortletApplication...), an access to the JavascriptManager * as well as a reference to the URLBuilder in use. * * It also contains a ThreadLocal object for an easy access. * * Context can be nested and hence a getParentAppRequestContext() is also available * */ abstract public class RequestContext { final static public String ACTION = "op"; private static ThreadLocal<RequestContext> tlocal_ = new ThreadLocal<RequestContext>() ; private Application app_ ; protected RequestContext parentAppRequestContext_ ; private Map<String, Object> attributes ; protected URLBuilder urlBuilder; public RequestContext(Application app) { app_ = app ; } public Application getApplication() { return app_ ; } public Locale getLocale() { return parentAppRequestContext_.getLocale() ; } public ResourceBundle getApplicationResourceBundle() { return null; } abstract public String getRequestParameter(String name) ; abstract public String[] getRequestParameterValues(String name) ; public JavascriptManager getJavascriptManager() { return getParentAppRequestContext().getJavascriptManager() ; } abstract public URLBuilder getURLBuilder() ; public String getRemoteUser() { return parentAppRequestContext_.getRemoteUser() ; } public boolean isUserInRole(String roleUser) { return parentAppRequestContext_.isUserInRole(roleUser) ; } abstract public boolean useAjax() ; public boolean getFullRender() { return true; } public ApplicationSession getApplicationSession() { throw new RuntimeException("This method is not supported"); } public Writer getWriter() throws Exception { return parentAppRequestContext_.getWriter() ; } final public Object getAttribute(String name) { if(attributes == null) return null ; return attributes.get(name) ; } final public void setAttribute(String name, Object value) { if(attributes == null) attributes = new HashMap<String, Object>() ; attributes.put(name, value) ; } final public Object getAttribute(Class type) { return getAttribute(type.getName()) ; } final public void setAttribute(Class type, Object value) { setAttribute(type.getName(), value) ; } public RequestContext getParentAppRequestContext() { return parentAppRequestContext_ ; } public void setParentAppRequestContext(RequestContext context) { parentAppRequestContext_ = context ; } @SuppressWarnings("unchecked") public static <T extends RequestContext> T getCurrentInstance() { return (T)tlocal_.get() ; } public static void setCurrentInstance(RequestContext ctx) { tlocal_.set(ctx) ; } }
/** * Created by The eXo Platform SAS * May 7, 2006 * * The main class to manage the request context in a webui environment * * It adds: * - some access to the root UI component (UIApplication) * - access to the request and response objects * - information about the current state of the request * - the list of object to be updated in an AJAX way * - an access to the ResourceResolver bound to an uri scheme * - the reference on the StateManager object */ abstract public class WebuiRequestContext extends RequestContext { protected UIApplication uiApplication_ ; protected String sessionId_ ; protected ResourceBundle appRes_ ; private StateManager stateManager_ ; private boolean responseComplete_ = false ; private boolean processRender_ = false ; private Throwable executionError_ ; private ArrayList<UIComponent> uicomponentToUpdateByAjax ; public WebuiRequestContext(Application app) { super(app) ; } public String getSessionId() { return sessionId_ ; } protected void setSessionId(String id) { sessionId_ = id ;} @SuppressWarnings("unchecked") public UIApplication getUIApplication() { return uiApplication_ ; } public void setUIApplication(UIApplication uiApplication) throws Exception { uiApplication_ = uiApplication ; appRes_ = getApplication().getResourceBundle(uiApplication.getLocale()) ; } public Locale getLocale() { return uiApplication_.getLocale() ;} public ResourceBundle getApplicationResourceBundle() { return appRes_ ; } public String getActionParameterName() { return WebuiRequestContext.ACTION ; } public String getUIComponentIdParameterName() { return UIComponent.UICOMPONENT; } abstract public String getRequestContextPath() ; abstract public <T> T getRequest() throws Exception ; abstract public <T> T getResponse() throws Exception ; public Throwable getExecutionError() { return executionError_ ; } public List<UIComponent> getUIComponentToUpdateByAjax() { return uicomponentToUpdateByAjax ; } public boolean isResponseComplete() { return responseComplete_ ;} public void setResponseComplete(boolean b) { responseComplete_ = b ; } public boolean getProcessRender() { return processRender_ ;} public void setProcessRender(boolean b) { processRender_ = b; } public void addUIComponentToUpdateByAjax(UIComponent uicomponent) { if(uicomponentToUpdateByAjax == null) { uicomponentToUpdateByAjax = new ArrayList<UIComponent>() ; } uicomponentToUpdateByAjax.add(uicomponent) ; } public ResourceResolver getResourceResolver(String uri) { Application app = getApplication() ; while(app != null) { ApplicationResourceResolver appResolver = app.getResourceResolver() ; ResourceResolver resolver = appResolver.getResourceResolver(uri) ; if(resolver != null) return resolver ; RequestContext pcontext = getParentAppRequestContext() ; if(pcontext != null) app = pcontext.getApplication() ; else app =null ; } return null ; } public StateManager getStateManager() { return stateManager_; } public void setStateManager(StateManager manager) { stateManager_ = manager ; } }
if(state == null) { synchronized(uiApplications) { ConfigurationManager cmanager = app.getConfigurationManager() ; String uirootClass = cmanager.getApplication().getUIRootComponent() ; Class type = Thread.currentThread().getContextClassLoader().loadClass(uirootClass) ; UserPortalConfig config = getUserPortalConfig(pcontext) ; if(config == null) { HttpServletResponse response = pcontext.getResponse(); response.sendRedirect("/portal/portal-warning.html"); pcontext.setResponseComplete(true); return null; } pcontext.setAttribute(UserPortalConfig.class, config); UIPortalApplication uiApplication = (UIPortalApplication)app.createUIComponent(type, config.getPortalConfig().getFactoryId(), null, context) ; state = new PortalApplicationState(uiApplication, pcontext.getAccessPath()) ; uiApplications.put(context.getSessionId(), state) ; PortalContainer pcontainer = (PortalContainer) app.getApplicationServiceContainer() ; pcontainer.createSessionContainer(context.getSessionId(), uiApplication.getOwner()) ; } }
public <T extends UIComponent> T createUIComponent(Class<T> type, String configId, String id, WebuiRequestContext context) throws Exception{ Component config = configManager_.getComponentConfig(type, configId) ; if(config == null) { throw new Exception("Cannot find the configuration for the component " + type.getName() + ", configId " +configId) ; } T uicomponent = Util.createObject(type, config.getInitParams()); uicomponent.setComponentConfig(id, config) ; config.getUIComponentLifecycle().init(uicomponent, context) ; return type.cast(uicomponent) ; }
@ComponentConfigs({
@ComponentConfig (
lifecycle = UIPortalApplicationLifecycle.class,
template = "system:/groovy/portal/webui/workspace/UIPortalApplication.gtmpl",
initParams = @ParamConfig(name = "public.showControlWorkspace", value = "true" )
),
@ComponentConfig (
id = "office" ,
lifecycle = UIPortalApplicationLifecycle.class,
template = "system:/groovy/portal/webui/workspace/UIPortalApplication.gtmpl",
initParams = @ParamConfig( name = "public.showControlWorkspace", value = "false" )
)
})- if the nodePath is null (case of the first request) a call to super.processDecode(context) is made and we end the method here
- if the nodePath exist but is equals to the current one then we also call super and stops here
- if the requested nodePath is not equals to the current one , then an event of type PageNodeEvent.CHANGE_PAGE_NODE is sent to the asociated EventListener; a call to super is then done
public void processAction(UIComponent uicomponent, WebuiRequestContext context) throws Exception { UIPortalApplication uiApp = (UIPortalApplication) uicomponent ; String componentId = context.getRequestParameter(context.getUIComponentIdParameterName()) ; if(componentId == null) return; UIComponent uiTarget = uiApp.findComponentById(componentId); if(uiTarget == null) return ; if(uiTarget == uicomponent) super.processAction(uicomponent, context) ; uiTarget.processAction(context) ; }
/** * The processrender() method handles the creation of the returned HTML either for a full * page render or in the case of an AJAX call * * The first request, Ajax is not enabled (means no ajaxRequest parameter in the request) and * hence the super.processRender() method is called. This will hence call the processrender() of * the Lifecycle object as this method is not overidden in UIPortalApplicationLifecycle. There we * simply render the bounded template (groovy usually). Note that bounded template are also defined * in component annotations, so for the current class it is UIPortalApplication.gtmpl * * On second calls, request have the "ajaxRequest" parameter set to true in the URL. In that case * the algorithm is a bit more complex: * * a) The list of components that should be updated is extracted using the * context.getUIComponentToUpdateByAjax() method. That list was setup during the process action * phase * b) Portlets and other UI components to update are split in 2 different lists * c) Portlets full content are returned and set with the tag <div class="PortalResponse"> * d) Block to updates (which are UI components) are set within * the <div class="PortalResponseData"> tag * e) Then the scripts and the skins to reload are set in the <div class="PortalResponseScript"> * */ public void processRender(WebuiRequestContext context) throws Exception { Writer w = context.getWriter() ; if(!context.useAjax()) { super.processRender(context) ; } else { PortalRequestContext pcontext = (PortalRequestContext)context; List<UIComponent> list = context.getUIComponentToUpdateByAjax() ; List<UIPortlet> uiPortlets = new ArrayList<UIPortlet>(3); List<UIComponent> uiDataComponents = new ArrayList<UIComponent>(5); if(list != null) { for(UIComponent uicomponent : list) { if(uicomponent instanceof UIPortlet) uiPortlets.add((UIPortlet)uicomponent) ; else uiDataComponents.add(uicomponent) ; } } w.write("<div class=\"PortalResponse\">") ; if(!context.getFullRender()) { for(UIPortlet uiPortlet : uiPortlets) { uiPortlet.processRender(context) ; } } w. write("<div class=\"PortalResponseData\">"); for(UIComponent uicomponent : uiDataComponents) { renderBlockToUpdate(uicomponent, context, w) ; } String skin = getAddSkinScript(list); w. write("</div>"); w. write("<div class=\"PortalResponseScript\">"); w. write(pcontext.getJavascriptManager().getJavascript()); w. write("eXo.core.Browser.onLoad();\n"); w. write(pcontext.getJavascriptManager().getCustomizedOnLoadScript()) ; if(skin != null){ w. write(skin) ; } w. write("</div>") ; w.write("</div>") ; } }
on 28/05/2008 at 10:09