001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.LiferayPortletContext;
020    import com.liferay.portal.kernel.portlet.LiferayPortletRequestDispatcher;
021    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
022    import com.liferay.portal.kernel.servlet.DynamicServletRequest;
023    import com.liferay.portal.kernel.servlet.URLEncoder;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.CharPool;
026    import com.liferay.portal.kernel.util.JavaConstants;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.model.Portlet;
030    import com.liferay.portal.model.PortletApp;
031    import com.liferay.portal.servlet.NamespaceServletRequest;
032    import com.liferay.portal.struts.StrutsURLEncoder;
033    import com.liferay.portal.theme.ThemeDisplay;
034    import com.liferay.portal.util.PortalUtil;
035    import com.liferay.portal.util.WebKeys;
036    
037    import java.io.IOException;
038    
039    import java.util.HashMap;
040    import java.util.Map;
041    import java.util.Set;
042    
043    import javax.portlet.PortletContext;
044    import javax.portlet.PortletException;
045    import javax.portlet.PortletRequest;
046    import javax.portlet.PortletResponse;
047    import javax.portlet.RenderRequest;
048    import javax.portlet.RenderResponse;
049    
050    import javax.servlet.RequestDispatcher;
051    import javax.servlet.ServletException;
052    import javax.servlet.http.HttpServletRequest;
053    import javax.servlet.http.HttpServletResponse;
054    
055    import org.apache.struts.Globals;
056    
057    /**
058     * @author Brian Wing Shun Chan
059     * @author Brian Myunghun Kim
060     * @author Raymond Augé
061     */
062    public class PortletRequestDispatcherImpl
063            implements LiferayPortletRequestDispatcher {
064    
065            public PortletRequestDispatcherImpl(
066                    RequestDispatcher requestDispatcher, boolean named,
067                    PortletContext portletContext) {
068    
069                    this(requestDispatcher, named, portletContext, null);
070            }
071    
072            public PortletRequestDispatcherImpl(
073                    RequestDispatcher requestDispatcher, boolean named,
074                    PortletContext portletContext, String path) {
075    
076                    _requestDispatcher = requestDispatcher;
077                    _named = named;
078                    _liferayPortletContext = (LiferayPortletContext)portletContext;
079                    _path = path;
080    
081                    _portlet = _liferayPortletContext.getPortlet();
082            }
083    
084            public void forward(
085                            PortletRequest portletRequest, PortletResponse portletResponse)
086                    throws IllegalStateException, IOException, PortletException {
087    
088                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
089                            portletResponse);
090    
091                    if (response.isCommitted()) {
092                            throw new IllegalStateException("Response is already committed");
093                    }
094    
095                    try {
096                            dispatch(portletRequest, portletResponse, false, false);
097                    }
098                    catch (ServletException se) {
099                            _log.error(se, se);
100    
101                            throw new PortletException(se);
102                    }
103            }
104    
105            public void include(
106                            PortletRequest portletRequest, PortletResponse portletResponse)
107                    throws IOException, PortletException {
108    
109                    try {
110                            dispatch(portletRequest, portletResponse, false, true);
111                    }
112                    catch (ServletException se) {
113                            _log.error(se, se);
114    
115                            throw new PortletException(se);
116                    }
117            }
118    
119            public void include(
120                            PortletRequest portletRequest, PortletResponse portletResponse,
121                            boolean strutsURLEncoder)
122                    throws IOException, PortletException {
123    
124                    try {
125                            dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
126                    }
127                    catch (ServletException se) {
128                            _log.error(se, se);
129    
130                            throw new PortletException(se);
131                    }
132            }
133    
134            public void include(
135                            RenderRequest renderRequest, RenderResponse renderResponse)
136                    throws IOException, PortletException {
137    
138                    try {
139                            dispatch(renderRequest, renderResponse, false, true);
140                    }
141                    catch (ServletException se) {
142                            _log.error(se, se);
143    
144                            throw new PortletException(se);
145                    }
146            }
147    
148            protected void dispatch(
149                            PortletRequest portletRequest, PortletResponse portletResponse,
150                            boolean strutsURLEncoder, boolean include)
151                    throws IOException, ServletException {
152    
153                    if (!include) {
154                            if (portletResponse instanceof MimeResponseImpl) {
155                                    MimeResponseImpl mimeResponseImpl =
156                                            (MimeResponseImpl)portletResponse;
157    
158                                    if (mimeResponseImpl.isCalledFlushBuffer()) {
159                                            throw new IllegalStateException();
160                                    }
161                            }
162                    }
163    
164                    PortletRequestImpl portletRequestImpl =
165                            PortletRequestImpl.getPortletRequestImpl(portletRequest);
166                    PortletResponseImpl portletResponseImpl =
167                            PortletResponseImpl.getPortletResponseImpl(portletResponse);
168    
169                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
170                            portletRequest);
171                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
172                            portletResponse);
173    
174                    request.setAttribute(
175                            JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest);
176                    request.setAttribute(
177                            JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse);
178    
179                    String pathInfo = null;
180                    String queryString = null;
181                    String requestURI = null;
182                    String servletPath = null;
183    
184                    if (_path != null) {
185                            String pathNoQueryString = _path;
186    
187                            int pos = _path.indexOf(CharPool.QUESTION);
188    
189                            if (pos != -1) {
190                                    pathNoQueryString = _path.substring(0, pos);
191                                    queryString = _path.substring(pos + 1);
192    
193                                    Map<String, String[]> queryParams =
194                                            new HashMap<String, String[]>();
195    
196                                    String[] queryParamsArray = StringUtil.split(
197                                            queryString, CharPool.AMPERSAND);
198    
199                                    for (String element : queryParamsArray) {
200                                            String[] nameValuePair = StringUtil.split(
201                                                    element, CharPool.EQUAL);
202    
203                                            String name = nameValuePair[0];
204                                            String value = StringPool.BLANK;
205    
206                                            if (nameValuePair.length == 2) {
207                                                    value = nameValuePair[1];
208                                            }
209    
210                                            String[] values = queryParams.get(name);
211    
212                                            if (values == null) {
213                                                    queryParams.put(name, new String[] {value});
214                                            }
215                                            else {
216                                                    String[] newValues = new String[values.length + 1];
217    
218                                                    System.arraycopy(
219                                                            values, 0, newValues, 0, values.length);
220    
221                                                    newValues[newValues.length - 1] = value;
222    
223                                                    queryParams.put(name, newValues);
224                                            }
225                                    }
226    
227                                    DynamicServletRequest dynamicRequest = null;
228    
229                                    if (portletRequestImpl.isPrivateRequestAttributes()) {
230                                            String portletNamespace = PortalUtil.getPortletNamespace(
231                                                    portletRequestImpl.getPortletName());
232    
233                                            dynamicRequest = new NamespaceServletRequest(
234                                                    request, portletNamespace, portletNamespace);
235                                    }
236                                    else {
237                                            dynamicRequest = new DynamicServletRequest(request);
238                                    }
239    
240                                    for (Map.Entry<String, String[]> entry :
241                                                    queryParams.entrySet()) {
242    
243                                            String name = entry.getKey();
244                                            String[] values = entry.getValue();
245    
246                                            String[] oldValues = dynamicRequest.getParameterValues(
247                                                    name);
248    
249                                            if (oldValues == null) {
250                                                    dynamicRequest.setParameterValues(name, values);
251                                            }
252                                            else {
253                                                    String[] newValues = ArrayUtil.append(
254                                                            values, oldValues);
255    
256                                                    dynamicRequest.setParameterValues(name, newValues);
257                                            }
258                                    }
259    
260                                    request = dynamicRequest;
261                            }
262    
263                            Portlet portlet = portletRequestImpl.getPortlet();
264    
265                            PortletApp portletApp = portlet.getPortletApp();
266    
267                            Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
268    
269                            for (String urlPattern : servletURLPatterns) {
270                                    if (urlPattern.endsWith("/*")) {
271                                            pos = urlPattern.indexOf("/*");
272    
273                                            urlPattern = urlPattern.substring(0, pos);
274    
275                                            if (pathNoQueryString.startsWith(urlPattern)) {
276                                                    pathInfo = pathNoQueryString.substring(
277                                                            urlPattern.length());
278                                                    servletPath = urlPattern;
279    
280                                                    break;
281                                            }
282                                    }
283                            }
284    
285                            if ((pathInfo == null) && (servletPath == null)) {
286                                    pathInfo = pathNoQueryString;
287                            }
288    
289                            String contextPath = portletRequest.getContextPath();
290    
291                            if (contextPath.equals(StringPool.SLASH)) {
292                                    requestURI = pathNoQueryString;
293                            }
294                            else {
295                                    requestURI = contextPath + pathNoQueryString;
296                            }
297                    }
298    
299                    PortletServletRequest portletServletRequest = new PortletServletRequest(
300                            request, portletRequest, pathInfo, queryString, requestURI,
301                            servletPath, _named, include);
302    
303                    PortletServletResponse portletServletResponse =
304                            new PortletServletResponse(response, portletResponse, include);
305    
306                    URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
307    
308                    if (urlEncoder != null) {
309                            portletResponseImpl.setURLEncoder(urlEncoder);
310                    }
311                    else if (strutsURLEncoder) {
312                            ThemeDisplay themeDisplay =
313                                    (ThemeDisplay)portletRequest.getAttribute(
314                                            WebKeys.THEME_DISPLAY);
315    
316                            URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
317                                    portletServletRequest.getContextPath(),
318                                    themeDisplay.getPathMain(),
319                                    (String)_liferayPortletContext.getAttribute(
320                                            Globals.SERVLET_KEY),
321                                    (LiferayPortletURL)portletResponseImpl.createRenderURL());
322    
323                            portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
324                    }
325    
326                    if (include) {
327                            _requestDispatcher.include(
328                                    portletServletRequest, portletServletResponse);
329                    }
330                    else {
331                            _requestDispatcher.forward(
332                                    portletServletRequest, portletServletResponse);
333                    }
334            }
335    
336            private static Log _log = LogFactoryUtil.getLog(
337                    PortletRequestDispatcherImpl.class);
338    
339            private LiferayPortletContext _liferayPortletContext;
340            private boolean _named;
341            private String _path;
342            private Portlet _portlet;
343            private RequestDispatcher _requestDispatcher;
344    
345    }