com.liferay.portlet.InvokerPortletImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portlet.InvokerPortletImpl.java

Source

/**
 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
 *
 * This library 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 library 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.
 */

package com.liferay.portlet;

import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.PortletFilterUtil;
import com.liferay.portal.kernel.servlet.PortletServlet;
import com.liferay.portal.kernel.servlet.StringServletResponse;
import com.liferay.portal.kernel.util.ClassUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.JavaConstants;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Time;
import com.liferay.portal.model.Layout;
import com.liferay.portal.model.PortletApp;
import com.liferay.portal.tools.deploy.PortletDeployer;
import com.liferay.portal.util.WebKeys;

import java.io.IOException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.filter.ActionFilter;
import javax.portlet.filter.EventFilter;
import javax.portlet.filter.FilterChain;
import javax.portlet.filter.PortletFilter;
import javax.portlet.filter.RenderFilter;
import javax.portlet.filter.ResourceFilter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.time.StopWatch;

/**
 * @author Brian Wing Shun Chan
 * @author Brian Myunghun Kim
 */
public class InvokerPortletImpl implements InvokerPortlet {

    public static void clearResponse(HttpSession session, long plid, String portletId, String languageId) {

        String sesResponseId = encodeResponseKey(plid, portletId, languageId);

        getResponses(session).remove(sesResponseId);
    }

    public static void clearResponses(HttpSession session) {
        getResponses(session).clear();
    }

    public static void clearResponses(PortletSession session) {
        getResponses(session).clear();
    }

    public static String encodeResponseKey(long plid, String portletId, String languageId) {

        StringBundler sb = new StringBundler(5);

        sb.append(StringUtil.toHexString(plid));
        sb.append(StringPool.UNDERLINE);
        sb.append(portletId);
        sb.append(StringPool.UNDERLINE);
        sb.append(languageId);

        return sb.toString();
    }

    public static Map<String, InvokerPortletResponse> getResponses(HttpSession session) {

        Map<String, InvokerPortletResponse> responses = (Map<String, InvokerPortletResponse>) session
                .getAttribute(WebKeys.CACHE_PORTLET_RESPONSES);

        if (responses == null) {
            responses = new ConcurrentHashMap<String, InvokerPortletResponse>();

            session.setAttribute(WebKeys.CACHE_PORTLET_RESPONSES, responses);
        }

        return responses;
    }

    public static Map<String, InvokerPortletResponse> getResponses(PortletSession portletSession) {

        return getResponses(((PortletSessionImpl) portletSession).getHttpSession());
    }

    public InvokerPortlet create(com.liferay.portal.model.Portlet portletModel, Portlet portlet,
            PortletContext portletContext) throws PortletException {

        try {
            InvokerPortlet invokerPortlet = (InvokerPortlet) clone();

            invokerPortlet.prepare(portletModel, portlet, portletContext);

            return invokerPortlet;
        } catch (PortletException pe) {
            throw pe;
        } catch (Exception e) {
            throw new PortletException(e);
        }
    }

    public InvokerPortlet create(com.liferay.portal.model.Portlet portletModel, Portlet portlet,
            PortletConfig portletConfig, PortletContext portletContext, boolean checkAuthToken,
            boolean facesPortlet, boolean strutsPortlet, boolean strutsBridgePortlet) throws PortletException {

        try {
            InvokerPortlet invokerPortlet = (InvokerPortlet) clone();

            invokerPortlet.prepare(portletModel, portlet, portletConfig, portletContext, checkAuthToken,
                    facesPortlet, strutsPortlet, strutsBridgePortlet);

            return invokerPortlet;
        } catch (PortletException pe) {
            throw pe;
        } catch (Exception e) {
            throw new PortletException(e);
        }
    }

    public void destroy() {
        if (_destroyable) {
            Thread currentThread = Thread.currentThread();

            ClassLoader contextClassLoader = currentThread.getContextClassLoader();

            ClassLoader portletClassLoader = getPortletClassLoader();

            try {
                if (portletClassLoader != null) {
                    currentThread.setContextClassLoader(portletClassLoader);
                }

                removePortletFilters();

                _portlet.destroy();
            } finally {
                if (portletClassLoader != null) {
                    currentThread.setContextClassLoader(contextClassLoader);
                }
            }
        }

        _destroyable = false;
    }

    public Portlet getPortlet() {
        return _portlet;
    }

    public ClassLoader getPortletClassLoader() {
        return (ClassLoader) _portletContextImpl.getAttribute(PortletServlet.PORTLET_CLASS_LOADER);
    }

    public PortletConfigImpl getPortletConfig() {
        return _portletConfigImpl;
    }

    public PortletContextImpl getPortletContext() {
        return _portletContextImpl;
    }

    public Portlet getPortletInstance() {
        return _portlet;
    }

    public Integer getExpCache() {
        return _expCache;
    }

    public void init(PortletConfig portletConfig) throws PortletException {
        _portletConfigImpl = (PortletConfigImpl) portletConfig;

        Thread currentThread = Thread.currentThread();

        ClassLoader contextClassLoader = currentThread.getContextClassLoader();

        ClassLoader portletClassLoader = getPortletClassLoader();

        try {
            if (portletClassLoader != null) {
                currentThread.setContextClassLoader(portletClassLoader);
            }

            _portlet.init(portletConfig);
        } finally {
            if (portletClassLoader != null) {
                currentThread.setContextClassLoader(contextClassLoader);
            }
        }

        _destroyable = true;
    }

    public boolean isCheckAuthToken() {
        return _checkAuthToken;
    }

    public boolean isDestroyable() {
        return _destroyable;
    }

    public boolean isFacesPortlet() {
        return _facesPortlet;
    }

    public boolean isStrutsBridgePortlet() {
        return _strutsBridgePortlet;
    }

    public boolean isStrutsPortlet() {
        return _strutsPortlet;
    }

    public void prepare(com.liferay.portal.model.Portlet portletModel, Portlet portlet,
            PortletContext portletContext) throws PortletException {

        _portletModel = portletModel;
        _portletId = _portletModel.getPortletId();
        _portlet = portlet;
        _portletContextImpl = (PortletContextImpl) portletContext;

        if (_log.isDebugEnabled()) {
            _log.debug("Create root cache wrapper for " + _portletContextImpl.getPortlet().getPortletId());
        }

        Map<String, String> initParams = portletModel.getInitParams();

        _checkAuthToken = GetterUtil.getBoolean(initParams.get("check-auth-token"), true);

        if (ClassUtil.isSubclass(_portlet.getClass(), PortletDeployer.JSF_MYFACES)
                || ClassUtil.isSubclass(_portlet.getClass(), PortletDeployer.JSF_STANDARD)
                || ClassUtil.isSubclass(_portlet.getClass(), PortletDeployer.JSF_SUN)) {

            _facesPortlet = true;
        }

        _strutsPortlet = ClassUtil.isSubclass(portlet.getClass(), StrutsPortlet.class);
        _strutsBridgePortlet = ClassUtil.isSubclass(portlet.getClass(),
                "org.apache.portals.bridges.struts.StrutsPortlet");
        _expCache = portletModel.getExpCache();
        setPortletFilters();
    }

    public void prepare(com.liferay.portal.model.Portlet portletModel, Portlet portlet, PortletConfig portletConfig,
            PortletContext portletContext, boolean checkAuthToken, boolean facesPortlet, boolean strutsPortlet,
            boolean strutsBridgePortlet) throws PortletException {

        // From prepare

        _portletModel = portletModel;
        _portlet = portlet;
        _portletId = _portletModel.getPortletId();
        _portletContextImpl = (PortletContextImpl) portletContext;
        _checkAuthToken = checkAuthToken;
        _facesPortlet = facesPortlet;
        _strutsPortlet = strutsPortlet;
        _strutsBridgePortlet = strutsBridgePortlet;
        _expCache = portletModel.getExpCache();
        setPortletFilters();

        if (_log.isDebugEnabled()) {
            _log.debug("Create instance cache wrapper for " + _portletContextImpl.getPortlet().getPortletId());
        }

        // From init

        _portletConfigImpl = (PortletConfigImpl) portletConfig;
    }

    public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws IOException {

        StopWatch stopWatch = null;

        if (_log.isDebugEnabled()) {
            stopWatch = new StopWatch();

            stopWatch.start();
        }

        try {
            invokeAction(actionRequest, actionResponse);
        } catch (PortletException pe) {
            actionRequest.setAttribute(_portletId + PortletException.class.getName(), pe);
        }

        if (_log.isDebugEnabled()) {
            if (stopWatch != null) {
                _log.debug("processAction for " + _portletId + " takes " + stopWatch.getTime() + " ms");
            } else {
                _log.debug("processAction for " + _portletId + " is finished");
            }
        }
    }

    public void processEvent(EventRequest eventRequest, EventResponse eventResponse)
            throws IOException, PortletException {

        StopWatch stopWatch = null;

        if (_log.isDebugEnabled()) {
            stopWatch = new StopWatch();

            stopWatch.start();
        }

        invokeEvent(eventRequest, eventResponse);

        if (_log.isDebugEnabled()) {
            _log.debug("processEvent for " + _portletId + " takes " + stopWatch.getTime() + " ms");
        }
    }

    public void render(RenderRequest renderRequest, RenderResponse renderResponse)
            throws IOException, PortletException {

        PortletException portletException = (PortletException) renderRequest
                .getAttribute(_portletId + PortletException.class.getName());

        if (portletException != null) {
            throw portletException;
        }

        StopWatch stopWatch = null;

        if (_log.isDebugEnabled()) {
            stopWatch = new StopWatch();

            stopWatch.start();
        }

        String remoteUser = renderRequest.getRemoteUser();

        if ((remoteUser == null) || (_expCache == null) || (_expCache.intValue() == 0)) {

            invokeRender(renderRequest, renderResponse);
        } else {
            RenderResponseImpl renderResponseImpl = (RenderResponseImpl) renderResponse;

            StringServletResponse stringResponse = (StringServletResponse) renderResponseImpl
                    .getHttpServletResponse();

            PortletSession portletSession = renderRequest.getPortletSession();

            long now = System.currentTimeMillis();

            Layout layout = (Layout) renderRequest.getAttribute(WebKeys.LAYOUT);

            Map<String, InvokerPortletResponse> sessionResponses = getResponses(portletSession);

            String sessionResponseId = encodeResponseKey(layout.getPlid(), _portletId,
                    LanguageUtil.getLanguageId(renderRequest));

            InvokerPortletResponse response = sessionResponses.get(sessionResponseId);

            if (response == null) {
                String title = invokeRender(renderRequest, renderResponse);

                response = new InvokerPortletResponse(title, stringResponse.getString(),
                        now + Time.SECOND * _expCache.intValue());

                sessionResponses.put(sessionResponseId, response);
            } else if ((response.getTime() < now) && (_expCache.intValue() > 0)) {
                String title = invokeRender(renderRequest, renderResponse);

                response.setTitle(title);
                response.setContent(stringResponse.getString());
                response.setTime(now + Time.SECOND * _expCache.intValue());
            } else {
                renderResponseImpl.setTitle(response.getTitle());
                stringResponse.getWriter().print(response.getContent());
            }
        }

        Map<String, String[]> properties = ((RenderResponseImpl) renderResponse).getProperties();

        if (properties.containsKey("clear-request-parameters")) {
            Map<String, String[]> renderParameters = ((RenderRequestImpl) renderRequest).getRenderParameters();

            renderParameters.clear();
        }

        if (_log.isDebugEnabled()) {
            _log.debug("render for " + _portletId + " takes " + stopWatch.getTime() + " ms");
        }
    }

    public void serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse)
            throws IOException {

        StopWatch stopWatch = null;

        if (_log.isDebugEnabled()) {
            stopWatch = new StopWatch();

            stopWatch.start();
        }

        try {
            invokeResource(resourceRequest, resourceResponse);
        } catch (PortletException pe) {
            resourceRequest.setAttribute(_portletId + PortletException.class.getName(), pe);
        }

        if (_log.isDebugEnabled()) {
            _log.debug("serveResource for " + _portletId + " takes " + stopWatch.getTime() + " ms");
        }
    }

    public void setPortletFilters() throws PortletException {
        PortletApp portletApp = _portletModel.getPortletApp();

        PortletContextBag portletContextBag = PortletContextBagPool.get(portletApp.getServletContextName());

        if (portletApp.isWARFile() && (portletContextBag == null)) {
            return;
        }

        removePortletFilters();

        Map<String, com.liferay.portal.model.PortletFilter> portletFilters = _portletModel.getPortletFilters();

        for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry : portletFilters.entrySet()) {

            com.liferay.portal.model.PortletFilter portletFilterModel = entry.getValue();

            PortletFilter portletFilter = PortletFilterFactory.create(portletFilterModel, _portletContextImpl);

            Set<String> lifecycles = portletFilterModel.getLifecycles();

            if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
                List<ActionFilter> actionFilters = _actionFiltersMap.get(_portletId);

                if (actionFilters == null) {
                    actionFilters = new ArrayList<ActionFilter>();
                }

                actionFilters.add((ActionFilter) portletFilter);

                _actionFiltersMap.put(_portletId, actionFilters);
            }

            if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
                List<EventFilter> eventFilters = _eventFiltersMap.get(_portletId);

                if (eventFilters == null) {
                    eventFilters = new ArrayList<EventFilter>();
                }

                eventFilters.add((EventFilter) portletFilter);

                _eventFiltersMap.put(_portletId, eventFilters);
            }

            if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
                List<RenderFilter> renderFilters = _renderFiltersMap.get(_portletId);

                if (renderFilters == null) {
                    renderFilters = new ArrayList<RenderFilter>();
                }

                renderFilters.add((RenderFilter) portletFilter);

                _renderFiltersMap.put(_portletId, renderFilters);
            }

            if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
                List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(_portletId);

                if (resourceFilters == null) {
                    resourceFilters = new ArrayList<ResourceFilter>();
                }

                resourceFilters.add((ResourceFilter) portletFilter);

                _resourceFiltersMap.put(_portletId, resourceFilters);
            }
        }
    }

    protected void invoke(LiferayPortletRequest portletRequest, LiferayPortletResponse portletResponse,
            String lifecycle, List<? extends PortletFilter> filters) throws IOException, PortletException {

        FilterChain filterChain = new FilterChainImpl(_portlet, filters);

        if (_portletConfigImpl.isWARFile()) {
            String invokerPortletName = _portletConfigImpl.getInitParameter(INIT_INVOKER_PORTLET_NAME);

            if (invokerPortletName == null) {
                invokerPortletName = _portletConfigImpl.getPortletName();
            }

            String path = StringPool.SLASH + invokerPortletName + "/invoke";

            RequestDispatcher requestDispatcher = _portletContextImpl.getServletContext()
                    .getRequestDispatcher(path);

            HttpServletRequest request = portletRequest.getHttpServletRequest();
            HttpServletResponse response = portletResponse.getHttpServletResponse();

            request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
            request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
            request.setAttribute(PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);

            try {

                // Resource phase must be a forward because includes do not
                // allow you to specify the content type or headers

                if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
                    requestDispatcher.forward(request, response);
                } else {
                    requestDispatcher.include(request, response);
                }
            } catch (ServletException se) {
                Throwable cause = se.getRootCause();

                if (cause instanceof PortletException) {
                    throw (PortletException) cause;
                }

                throw new PortletException(cause);
            }
        } else {
            PortletFilterUtil.doFilter(portletRequest, portletResponse, lifecycle, filterChain);
        }

        portletResponse.transferMarkupHeadElements();

        Map<String, String[]> properties = portletResponse.getProperties();

        if ((properties != null) && (properties.size() > 0)) {
            if (_expCache != null) {
                String[] expCache = properties.get(RenderResponse.EXPIRATION_CACHE);

                if ((expCache != null) && (expCache.length > 0) && (expCache[0] != null)) {

                    _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
                }
            }
        }
    }

    protected void invokeAction(ActionRequest actionRequest, ActionResponse actionResponse)
            throws IOException, PortletException {

        LiferayPortletRequest portletRequest = (LiferayPortletRequest) actionRequest;
        LiferayPortletResponse portletResponse = (LiferayPortletResponse) actionResponse;

        String portletId = _getPortletId(portletResponse);

        List<ActionFilter> actionFilters = _actionFiltersMap.get(portletId);

        invoke(portletRequest, portletResponse, PortletRequest.ACTION_PHASE, actionFilters);
    }

    protected void invokeEvent(EventRequest eventRequest, EventResponse eventResponse)
            throws IOException, PortletException {

        LiferayPortletRequest portletRequest = (LiferayPortletRequest) eventRequest;
        LiferayPortletResponse portletResponse = (LiferayPortletResponse) eventResponse;

        String portletId = _getPortletId(portletResponse);

        List<EventFilter> eventFilters = _eventFiltersMap.get(portletId);

        invoke(portletRequest, portletResponse, PortletRequest.EVENT_PHASE, eventFilters);
    }

    protected String invokeRender(RenderRequest renderRequest, RenderResponse renderResponse)
            throws IOException, PortletException {

        LiferayPortletRequest portletRequest = (LiferayPortletRequest) renderRequest;
        LiferayPortletResponse portletResponse = (LiferayPortletResponse) renderResponse;

        String portletId = _getPortletId(portletResponse);

        List<RenderFilter> renderFilters = _renderFiltersMap.get(portletId);

        invoke(portletRequest, portletResponse, PortletRequest.RENDER_PHASE, renderFilters);

        RenderResponseImpl renderResponseImpl = (RenderResponseImpl) renderResponse;

        return renderResponseImpl.getTitle();
    }

    protected void invokeResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse)
            throws IOException, PortletException {

        LiferayPortletRequest portletRequest = (LiferayPortletRequest) resourceRequest;
        LiferayPortletResponse portletResponse = (LiferayPortletResponse) resourceResponse;

        String portletId = _getPortletId(portletResponse);

        List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(portletId);

        invoke(portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE, resourceFilters);
    }

    protected void removePortletFilters() {
        _actionFiltersMap.remove(_portletId);
        _eventFiltersMap.remove(_portletId);
        _renderFiltersMap.remove(_portletId);
        _resourceFiltersMap.remove(_portletId);
    }

    private String _getPortletId(LiferayPortletResponse portletResponse) {
        PortletResponseImpl portletResponseImpl = (PortletResponseImpl) portletResponse;

        com.liferay.portal.model.Portlet portlet = portletResponseImpl.getPortlet();

        return portlet.getPortletId();
    }

    private static Log _log = LogFactoryUtil.getLog(InvokerPortletImpl.class);

    private com.liferay.portal.model.Portlet _portletModel;
    private String _portletId;
    private Portlet _portlet;
    private PortletConfigImpl _portletConfigImpl;
    private PortletContextImpl _portletContextImpl;
    private Integer _expCache;
    private boolean _checkAuthToken;
    private boolean _destroyable;
    private boolean _facesPortlet;
    private boolean _strutsPortlet;
    private boolean _strutsBridgePortlet;
    private Map<String, List<ActionFilter>> _actionFiltersMap = new HashMap<String, List<ActionFilter>>();
    private Map<String, List<EventFilter>> _eventFiltersMap = new HashMap<String, List<EventFilter>>();
    private Map<String, List<RenderFilter>> _renderFiltersMap = new HashMap<String, List<RenderFilter>>();
    private Map<String, List<ResourceFilter>> _resourceFiltersMap = new HashMap<String, List<ResourceFilter>>();

}