1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
20  import com.liferay.portal.kernel.servlet.URLEncoder;
21  import com.liferay.portal.kernel.util.ArrayUtil;
22  import com.liferay.portal.kernel.util.JavaConstants;
23  import com.liferay.portal.kernel.util.StringPool;
24  import com.liferay.portal.kernel.util.StringUtil;
25  import com.liferay.portal.model.Portlet;
26  import com.liferay.portal.model.PortletApp;
27  import com.liferay.portal.servlet.NamespaceServletRequest;
28  import com.liferay.portal.struts.StrutsURLEncoder;
29  import com.liferay.portal.theme.ThemeDisplay;
30  import com.liferay.portal.util.PortalUtil;
31  import com.liferay.portal.util.WebKeys;
32  import com.liferay.util.servlet.DynamicServletRequest;
33  
34  import java.io.IOException;
35  
36  import java.util.HashMap;
37  import java.util.Map;
38  import java.util.Set;
39  
40  import javax.portlet.PortletException;
41  import javax.portlet.PortletRequest;
42  import javax.portlet.PortletRequestDispatcher;
43  import javax.portlet.PortletResponse;
44  import javax.portlet.RenderRequest;
45  import javax.portlet.RenderResponse;
46  
47  import javax.servlet.RequestDispatcher;
48  import javax.servlet.ServletException;
49  import javax.servlet.http.HttpServletRequest;
50  import javax.servlet.http.HttpServletResponse;
51  
52  import org.apache.struts.Globals;
53  
54  /**
55   * <a href="PortletRequestDispatcherImpl.java.html"><b><i>View Source</i></b>
56   * </a>
57   *
58   * @author Brian Wing Shun Chan
59   * @author Brian Myunghun Kim
60   */
61  public class PortletRequestDispatcherImpl implements PortletRequestDispatcher {
62  
63      public PortletRequestDispatcherImpl(
64          RequestDispatcher requestDispatcher, boolean named,
65          PortletContextImpl portletContextImpl) {
66  
67          this(requestDispatcher, named, portletContextImpl, null);
68      }
69  
70      public PortletRequestDispatcherImpl(
71          RequestDispatcher requestDispatcher, boolean named,
72          PortletContextImpl portletContextImpl, String path) {
73  
74          _requestDispatcher = requestDispatcher;
75          _named = named;
76          _portlet = portletContextImpl.getPortlet();
77          _portletContextImpl = portletContextImpl;
78          _path = path;
79      }
80  
81      public void forward(
82              PortletRequest portletRequest, PortletResponse portletResponse)
83          throws IllegalStateException, IOException, PortletException {
84  
85          HttpServletResponse response = PortalUtil.getHttpServletResponse(
86              portletResponse);
87  
88          if (response.isCommitted()) {
89              throw new IllegalStateException("Response is already committed");
90          }
91  
92          try {
93              dispatch(portletRequest, portletResponse, false, false);
94          }
95          catch (ServletException se) {
96              _log.error(se, se);
97  
98              throw new PortletException(se);
99          }
100     }
101 
102     public void include(
103             PortletRequest portletRequest, PortletResponse portletResponse)
104         throws IOException, PortletException {
105 
106         try {
107             dispatch(portletRequest, portletResponse, false, true);
108         }
109         catch (ServletException se) {
110             _log.error(se, se);
111 
112             throw new PortletException(se);
113         }
114     }
115 
116     public void include(
117             PortletRequest portletRequest, PortletResponse portletResponse,
118             boolean strutsURLEncoder)
119         throws IOException, PortletException {
120 
121         try {
122             dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
123         }
124         catch (ServletException se) {
125             _log.error(se, se);
126 
127             throw new PortletException(se);
128         }
129     }
130 
131     public void include(
132             RenderRequest renderRequest, RenderResponse renderResponse)
133         throws IOException, PortletException {
134 
135         try {
136             dispatch(renderRequest, renderResponse, false, true);
137         }
138         catch (ServletException se) {
139             _log.error(se, se);
140 
141             throw new PortletException(se);
142         }
143     }
144 
145     protected void dispatch(
146             PortletRequest portletRequest, PortletResponse portletResponse,
147             boolean strutsURLEncoder, boolean include)
148         throws IOException, ServletException {
149 
150         if (!include) {
151             if (portletResponse instanceof MimeResponseImpl) {
152                 MimeResponseImpl mimeResponseImpl =
153                     (MimeResponseImpl)portletResponse;
154 
155                 if (mimeResponseImpl.isCalledFlushBuffer()) {
156                     throw new IllegalStateException();
157                 }
158             }
159         }
160 
161         PortletRequestImpl portletRequestImpl =
162             PortletRequestImpl.getPortletRequestImpl(portletRequest);
163         PortletResponseImpl portletResponseImpl =
164             PortletResponseImpl.getPortletResponseImpl(portletResponse);
165 
166         HttpServletRequest request = PortalUtil.getHttpServletRequest(
167             portletRequest);
168         HttpServletResponse response = PortalUtil.getHttpServletResponse(
169             portletResponse);
170 
171         request.setAttribute(
172             JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest);
173         request.setAttribute(
174             JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse);
175 
176         String pathInfo = null;
177         String queryString = null;
178         String requestURI = null;
179         String servletPath = null;
180 
181         if (_path != null) {
182             String pathNoQueryString = _path;
183 
184             int pos = _path.indexOf(StringPool.QUESTION);
185 
186             if (pos != -1) {
187                 pathNoQueryString = _path.substring(0, pos);
188                 queryString = _path.substring(pos + 1, _path.length());
189 
190                 Map<String, String[]> queryParams =
191                     new HashMap<String, String[]>();
192 
193                 String[] queryParamsArray = StringUtil.split(
194                     queryString, StringPool.AMPERSAND);
195 
196                 for (int i = 0; i < queryParamsArray.length; i++) {
197                     String[] nameValuePair = StringUtil.split(
198                         queryParamsArray[i], StringPool.EQUAL);
199 
200                     String name = nameValuePair[0];
201                     String value = StringPool.BLANK;
202 
203                     if (nameValuePair.length == 2) {
204                         value = nameValuePair[1];
205                     }
206 
207                     String[] values = queryParams.get(name);
208 
209                     if (values == null) {
210                         queryParams.put(name, new String[] {value});
211                     }
212                     else {
213                         String[] newValues = new String[values.length + 1];
214 
215                         System.arraycopy(
216                             values, 0, newValues, 0, values.length);
217 
218                         newValues[newValues.length - 1] = value;
219 
220                         queryParams.put(name, newValues);
221                     }
222                 }
223 
224                 DynamicServletRequest dynamicRequest = null;
225 
226                 if (portletRequestImpl.isPrivateRequestAttributes()) {
227                     String portletNamespace = PortalUtil.getPortletNamespace(
228                         portletRequestImpl.getPortletName());
229 
230                     dynamicRequest = new NamespaceServletRequest(
231                         request, portletNamespace, portletNamespace);
232                 }
233                 else {
234                     dynamicRequest = new DynamicServletRequest(request);
235                 }
236 
237                 for (Map.Entry<String, String[]> entry :
238                         queryParams.entrySet()) {
239 
240                     String name = entry.getKey();
241                     String[] values = entry.getValue();
242 
243                     String[] oldValues = dynamicRequest.getParameterValues(
244                         name);
245 
246                     if (oldValues == null) {
247                         dynamicRequest.setParameterValues(name, values);
248                     }
249                     else {
250                         String[] newValues = ArrayUtil.append(
251                             values, oldValues);
252 
253                         dynamicRequest.setParameterValues(name, newValues);
254                     }
255                 }
256 
257                 request = dynamicRequest;
258             }
259 
260             Portlet portlet = portletRequestImpl.getPortlet();
261 
262             PortletApp portletApp = portlet.getPortletApp();
263 
264             Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
265 
266             for (String urlPattern : servletURLPatterns) {
267                 if (urlPattern.endsWith("/*")) {
268                     pos = urlPattern.indexOf("/*");
269 
270                     urlPattern = urlPattern.substring(0, pos);
271 
272                     if (pathNoQueryString.startsWith(urlPattern)) {
273                         pathInfo = pathNoQueryString.substring(
274                             urlPattern.length());
275                         servletPath = urlPattern;
276 
277                         break;
278                     }
279                 }
280             }
281 
282             if ((pathInfo == null) && (servletPath == null)) {
283                 pathInfo = pathNoQueryString;
284                 servletPath = pathNoQueryString;
285             }
286 
287             requestURI = portletRequest.getContextPath() + pathNoQueryString;
288         }
289 
290         PortletServletRequest portletServletRequest = new PortletServletRequest(
291             request, portletRequestImpl, pathInfo, queryString, requestURI,
292             servletPath, _named, include);
293 
294         PortletServletResponse portletServletResponse =
295             new PortletServletResponse(response, portletResponseImpl, include);
296 
297         URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
298 
299         if (urlEncoder != null) {
300             portletResponseImpl.setURLEncoder(urlEncoder);
301         }
302         else if (strutsURLEncoder) {
303             ThemeDisplay themeDisplay =
304                 (ThemeDisplay)portletRequest.getAttribute(
305                     WebKeys.THEME_DISPLAY);
306 
307             URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
308                 portletServletRequest.getContextPath(),
309                 themeDisplay.getPathMain(),
310                 (String)_portletContextImpl.getAttribute(
311                     Globals.SERVLET_KEY),
312                 (LiferayPortletURL)portletResponseImpl.createRenderURL());
313 
314             portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
315         }
316 
317         if (include) {
318             _requestDispatcher.include(
319                 portletServletRequest, portletServletResponse);
320         }
321         else {
322             _requestDispatcher.forward(
323                 portletServletRequest, portletServletResponse);
324         }
325     }
326 
327     private static Log _log = LogFactoryUtil.getLog(
328         PortletRequestDispatcherImpl.class);
329 
330     private RequestDispatcher _requestDispatcher;
331     private boolean _named;
332     private Portlet _portlet;
333     private PortletContextImpl _portletContextImpl;
334     private String _path;
335 
336 }