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