/** * Copyright (c) 2000-present 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.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Portlet; import com.liferay.portal.kernel.model.PortletApp; import com.liferay.portal.kernel.portlet.LiferayPortletContext; import com.liferay.portal.kernel.portlet.LiferayPortletRequestDispatcher; import com.liferay.portal.kernel.portlet.LiferayPortletURL; import com.liferay.portal.kernel.servlet.URLEncoder; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.JavaConstants; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.servlet.DynamicServletRequestUtil; import com.liferay.portal.struts.StrutsURLEncoder; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.portlet.PortletContext; import javax.portlet.PortletException; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.Globals; /** * @author Brian Wing Shun Chan * @author Brian Myunghun Kim * @author Raymond Augé */ public class PortletRequestDispatcherImpl implements LiferayPortletRequestDispatcher { public PortletRequestDispatcherImpl( RequestDispatcher requestDispatcher, boolean named, PortletContext portletContext) { this(requestDispatcher, named, portletContext, null); } public PortletRequestDispatcherImpl( RequestDispatcher requestDispatcher, boolean named, PortletContext portletContext, String path) { _requestDispatcher = requestDispatcher; _named = named; _liferayPortletContext = (LiferayPortletContext)portletContext; _path = path; _portlet = _liferayPortletContext.getPortlet(); } @Override public void forward( PortletRequest portletRequest, PortletResponse portletResponse) throws IllegalStateException, IOException, PortletException { HttpServletResponse httpServletResponse = PortalUtil.getHttpServletResponse(portletResponse); if (httpServletResponse.isCommitted()) { throw new IllegalStateException("Response is already committed"); } dispatch(portletRequest, portletResponse, false, false); } @Override public void include( PortletRequest portletRequest, PortletResponse portletResponse) throws IOException, PortletException { dispatch(portletRequest, portletResponse, false, true); } @Override public void include( PortletRequest portletRequest, PortletResponse portletResponse, boolean strutsURLEncoder) throws IOException, PortletException { dispatch(portletRequest, portletResponse, strutsURLEncoder, true); } @Override public void include( RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException { dispatch(renderRequest, renderResponse, false, true); } protected void checkCalledFlushBuffer( boolean include, PortletResponse portletResponse) { if (!include && (portletResponse instanceof MimeResponseImpl)) { MimeResponseImpl mimeResponseImpl = (MimeResponseImpl)portletResponse; if (mimeResponseImpl.isCalledFlushBuffer()) { throw new IllegalStateException(); } } } protected HttpServletRequest createDynamicServletRequest( HttpServletRequest httpServletRequest, PortletRequestImpl portletRequestImpl, Map<String, String[]> parameterMap) { return DynamicServletRequestUtil.createDynamicServletRequest( httpServletRequest, portletRequestImpl.getPortlet(), parameterMap, true); } protected void dispatch( PortletRequest portletRequest, PortletResponse portletResponse, boolean strutsURLEncoder, boolean include) throws IOException, PortletException { checkCalledFlushBuffer(include, portletResponse); PortletRequestImpl portletRequestImpl = PortletRequestImpl.getPortletRequestImpl(portletRequest); PortletResponseImpl portletResponseImpl = PortletResponseImpl.getPortletResponseImpl(portletResponse); HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(portletRequest); httpServletRequest.setAttribute( JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest); httpServletRequest.setAttribute( JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse); String pathInfo = null; String queryString = null; String requestURI = null; String servletPath = null; if (_path != null) { String pathNoQueryString = _path; int pos = _path.indexOf(CharPool.QUESTION); if (pos != -1) { pathNoQueryString = _path.substring(0, pos); queryString = _path.substring(pos + 1); httpServletRequest = createDynamicServletRequest( httpServletRequest, portletRequestImpl, toParameterMap(queryString)); } Portlet portlet = portletRequestImpl.getPortlet(); PortletApp portletApp = portlet.getPortletApp(); Set<String> servletURLPatterns = portletApp.getServletURLPatterns(); for (String urlPattern : servletURLPatterns) { if (urlPattern.endsWith("/*")) { int length = urlPattern.length() - 2; if ((pathNoQueryString.length() > length) && pathNoQueryString.regionMatches( 0, urlPattern, 0, length) && (pathNoQueryString.charAt(length) == CharPool.SLASH)) { pathInfo = pathNoQueryString.substring(length); servletPath = urlPattern.substring(0, length); break; } } } if (pathInfo == null) { pathInfo = pathNoQueryString; } String contextPath = portletRequest.getContextPath(); if (contextPath.equals(StringPool.SLASH)) { requestURI = pathNoQueryString; } else { requestURI = contextPath + pathNoQueryString; } } PortletServletRequest portletServletRequest = new PortletServletRequest( httpServletRequest, portletRequest, pathInfo, queryString, requestURI, servletPath, _named, include); PortletServletResponse portletServletResponse = new PortletServletResponse( PortalUtil.getHttpServletResponse(portletResponse), portletResponse, include); URLEncoder urlEncoder = _portlet.getURLEncoderInstance(); if (urlEncoder != null) { portletResponseImpl.setURLEncoder(urlEncoder); } else if (strutsURLEncoder) { ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute( WebKeys.THEME_DISPLAY); URLEncoder strutsURLEncoderObj = new StrutsURLEncoder( portletServletRequest.getContextPath(), themeDisplay.getPathMain(), (String)_liferayPortletContext.getAttribute( Globals.SERVLET_KEY), (LiferayPortletURL)portletResponseImpl.createRenderURL()); portletResponseImpl.setURLEncoder(strutsURLEncoderObj); } try { if (include) { _requestDispatcher.include( portletServletRequest, portletServletResponse); } else { _requestDispatcher.forward( portletServletRequest, portletServletResponse); } } catch (ServletException se) { if (_log.isDebugEnabled()) { _log.debug(se); } _log.error(se.getMessage()); throw new PortletException(se); } } protected Map<String, String[]> toParameterMap(String queryString) { Map<String, String[]> parameterMap = new HashMap<>(); for (String parameter : StringUtil.split(queryString, CharPool.AMPERSAND)) { String[] parameterArray = StringUtil.split( parameter, CharPool.EQUAL); String name = parameterArray[0]; String value = StringPool.BLANK; if (parameterArray.length == 2) { value = parameterArray[1]; } String[] values = parameterMap.get(name); if (values == null) { parameterMap.put(name, new String[] {value}); } else { String[] newValues = new String[values.length + 1]; System.arraycopy(values, 0, newValues, 0, values.length); newValues[newValues.length - 1] = value; parameterMap.put(name, newValues); } } return parameterMap; } private static final Log _log = LogFactoryUtil.getLog( PortletRequestDispatcherImpl.class); private final LiferayPortletContext _liferayPortletContext; private final boolean _named; private final String _path; private final Portlet _portlet; private final RequestDispatcher _requestDispatcher; }