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            @Override
085            public void forward(
086                            PortletRequest portletRequest, PortletResponse portletResponse)
087                    throws IllegalStateException, IOException, PortletException {
088    
089                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
090                            portletResponse);
091    
092                    if (response.isCommitted()) {
093                            throw new IllegalStateException("Response is already committed");
094                    }
095    
096                    try {
097                            dispatch(portletRequest, portletResponse, false, false);
098                    }
099                    catch (ServletException se) {
100                            _log.error(se, se);
101    
102                            throw new PortletException(se);
103                    }
104            }
105    
106            @Override
107            public void include(
108                            PortletRequest portletRequest, PortletResponse portletResponse)
109                    throws IOException, PortletException {
110    
111                    try {
112                            dispatch(portletRequest, portletResponse, false, true);
113                    }
114                    catch (ServletException se) {
115                            _log.error(se, se);
116    
117                            throw new PortletException(se);
118                    }
119            }
120    
121            @Override
122            public void include(
123                            PortletRequest portletRequest, PortletResponse portletResponse,
124                            boolean strutsURLEncoder)
125                    throws IOException, PortletException {
126    
127                    try {
128                            dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
129                    }
130                    catch (ServletException se) {
131                            _log.error(se, se);
132    
133                            throw new PortletException(se);
134                    }
135            }
136    
137            @Override
138            public void include(
139                            RenderRequest renderRequest, RenderResponse renderResponse)
140                    throws IOException, PortletException {
141    
142                    try {
143                            dispatch(renderRequest, renderResponse, false, true);
144                    }
145                    catch (ServletException se) {
146                            _log.error(se, se);
147    
148                            throw new PortletException(se);
149                    }
150            }
151    
152            protected void dispatch(
153                            PortletRequest portletRequest, PortletResponse portletResponse,
154                            boolean strutsURLEncoder, boolean include)
155                    throws IOException, ServletException {
156    
157                    if (!include) {
158                            if (portletResponse instanceof MimeResponseImpl) {
159                                    MimeResponseImpl mimeResponseImpl =
160                                            (MimeResponseImpl)portletResponse;
161    
162                                    if (mimeResponseImpl.isCalledFlushBuffer()) {
163                                            throw new IllegalStateException();
164                                    }
165                            }
166                    }
167    
168                    PortletRequestImpl portletRequestImpl =
169                            PortletRequestImpl.getPortletRequestImpl(portletRequest);
170                    PortletResponseImpl portletResponseImpl =
171                            PortletResponseImpl.getPortletResponseImpl(portletResponse);
172    
173                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
174                            portletRequest);
175                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
176                            portletResponse);
177    
178                    request.setAttribute(
179                            JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest);
180                    request.setAttribute(
181                            JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse);
182    
183                    String pathInfo = null;
184                    String queryString = null;
185                    String requestURI = null;
186                    String servletPath = null;
187    
188                    if (_path != null) {
189                            String pathNoQueryString = _path;
190    
191                            int pos = _path.indexOf(CharPool.QUESTION);
192    
193                            if (pos != -1) {
194                                    pathNoQueryString = _path.substring(0, pos);
195                                    queryString = _path.substring(pos + 1);
196    
197                                    Map<String, String[]> queryParams =
198                                            new HashMap<String, String[]>();
199    
200                                    String[] queryParamsArray = StringUtil.split(
201                                            queryString, CharPool.AMPERSAND);
202    
203                                    for (String element : queryParamsArray) {
204                                            String[] nameValuePair = StringUtil.split(
205                                                    element, CharPool.EQUAL);
206    
207                                            String name = nameValuePair[0];
208                                            String value = StringPool.BLANK;
209    
210                                            if (nameValuePair.length == 2) {
211                                                    value = nameValuePair[1];
212                                            }
213    
214                                            String[] values = queryParams.get(name);
215    
216                                            if (values == null) {
217                                                    queryParams.put(name, new String[] {value});
218                                            }
219                                            else {
220                                                    String[] newValues = new String[values.length + 1];
221    
222                                                    System.arraycopy(
223                                                            values, 0, newValues, 0, values.length);
224    
225                                                    newValues[newValues.length - 1] = value;
226    
227                                                    queryParams.put(name, newValues);
228                                            }
229                                    }
230    
231                                    DynamicServletRequest dynamicRequest = null;
232    
233                                    if (portletRequestImpl.isPrivateRequestAttributes()) {
234                                            String portletNamespace = PortalUtil.getPortletNamespace(
235                                                    portletRequestImpl.getPortletName());
236    
237                                            dynamicRequest = new NamespaceServletRequest(
238                                                    request, portletNamespace, portletNamespace);
239                                    }
240                                    else {
241                                            dynamicRequest = new DynamicServletRequest(request);
242                                    }
243    
244                                    for (Map.Entry<String, String[]> entry :
245                                                    queryParams.entrySet()) {
246    
247                                            String name = entry.getKey();
248                                            String[] values = entry.getValue();
249    
250                                            String[] oldValues = dynamicRequest.getParameterValues(
251                                                    name);
252    
253                                            if (oldValues == null) {
254                                                    dynamicRequest.setParameterValues(name, values);
255                                            }
256                                            else {
257                                                    String[] newValues = ArrayUtil.append(
258                                                            values, oldValues);
259    
260                                                    dynamicRequest.setParameterValues(name, newValues);
261                                            }
262                                    }
263    
264                                    request = dynamicRequest;
265                            }
266    
267                            Portlet portlet = portletRequestImpl.getPortlet();
268    
269                            PortletApp portletApp = portlet.getPortletApp();
270    
271                            Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
272    
273                            for (String urlPattern : servletURLPatterns) {
274                                    if (urlPattern.endsWith("/*")) {
275                                            pos = urlPattern.indexOf("/*");
276    
277                                            urlPattern = urlPattern.substring(0, pos);
278    
279                                            if (pathNoQueryString.startsWith(urlPattern)) {
280                                                    pathInfo = pathNoQueryString.substring(
281                                                            urlPattern.length());
282                                                    servletPath = urlPattern;
283    
284                                                    break;
285                                            }
286                                    }
287                            }
288    
289                            if ((pathInfo == null) && (servletPath == null)) {
290                                    pathInfo = pathNoQueryString;
291                            }
292    
293                            String contextPath = portletRequest.getContextPath();
294    
295                            if (contextPath.equals(StringPool.SLASH)) {
296                                    requestURI = pathNoQueryString;
297                            }
298                            else {
299                                    requestURI = contextPath + pathNoQueryString;
300                            }
301                    }
302    
303                    PortletServletRequest portletServletRequest = new PortletServletRequest(
304                            request, portletRequest, pathInfo, queryString, requestURI,
305                            servletPath, _named, include);
306    
307                    PortletServletResponse portletServletResponse =
308                            new PortletServletResponse(response, portletResponse, include);
309    
310                    URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
311    
312                    if (urlEncoder != null) {
313                            portletResponseImpl.setURLEncoder(urlEncoder);
314                    }
315                    else if (strutsURLEncoder) {
316                            ThemeDisplay themeDisplay =
317                                    (ThemeDisplay)portletRequest.getAttribute(
318                                            WebKeys.THEME_DISPLAY);
319    
320                            URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
321                                    portletServletRequest.getContextPath(),
322                                    themeDisplay.getPathMain(),
323                                    (String)_liferayPortletContext.getAttribute(
324                                            Globals.SERVLET_KEY),
325                                    (LiferayPortletURL)portletResponseImpl.createRenderURL());
326    
327                            portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
328                    }
329    
330                    if (include) {
331                            _requestDispatcher.include(
332                                    portletServletRequest, portletServletResponse);
333                    }
334                    else {
335                            _requestDispatcher.forward(
336                                    portletServletRequest, portletServletResponse);
337                    }
338            }
339    
340            private static Log _log = LogFactoryUtil.getLog(
341                    PortletRequestDispatcherImpl.class);
342    
343            private LiferayPortletContext _liferayPortletContext;
344            private boolean _named;
345            private String _path;
346            private Portlet _portlet;
347            private RequestDispatcher _requestDispatcher;
348    
349    }