1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
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.CharPool;
23  import com.liferay.portal.kernel.util.JavaConstants;
24  import com.liferay.portal.kernel.util.StringPool;
25  import com.liferay.portal.kernel.util.StringUtil;
26  import com.liferay.portal.model.Portlet;
27  import com.liferay.portal.model.PortletApp;
28  import com.liferay.portal.servlet.NamespaceServletRequest;
29  import com.liferay.portal.struts.StrutsURLEncoder;
30  import com.liferay.portal.theme.ThemeDisplay;
31  import com.liferay.portal.util.PortalUtil;
32  import com.liferay.portal.util.WebKeys;
33  import com.liferay.util.servlet.DynamicServletRequest;
34  
35  import java.io.IOException;
36  
37  import java.util.HashMap;
38  import java.util.Map;
39  import java.util.Set;
40  
41  import javax.portlet.PortletException;
42  import javax.portlet.PortletRequest;
43  import javax.portlet.PortletRequestDispatcher;
44  import javax.portlet.PortletResponse;
45  import javax.portlet.RenderRequest;
46  import javax.portlet.RenderResponse;
47  
48  import javax.servlet.RequestDispatcher;
49  import javax.servlet.ServletException;
50  import javax.servlet.http.HttpServletRequest;
51  import javax.servlet.http.HttpServletResponse;
52  
53  import org.apache.struts.Globals;
54  
55  /**
56   * <a href="PortletRequestDispatcherImpl.java.html"><b><i>View Source</i></b>
57   * </a>
58   *
59   * @author Brian Wing Shun Chan
60   * @author Brian Myunghun Kim
61   */
62  public class PortletRequestDispatcherImpl implements PortletRequestDispatcher {
63  
64      public PortletRequestDispatcherImpl(
65          RequestDispatcher requestDispatcher, boolean named,
66          PortletContextImpl portletContextImpl) {
67  
68          this(requestDispatcher, named, portletContextImpl, null);
69      }
70  
71      public PortletRequestDispatcherImpl(
72          RequestDispatcher requestDispatcher, boolean named,
73          PortletContextImpl portletContextImpl, String path) {
74  
75          _requestDispatcher = requestDispatcher;
76          _named = named;
77          _portlet = portletContextImpl.getPortlet();
78          _portletContextImpl = portletContextImpl;
79          _path = path;
80      }
81  
82      public void forward(
83              PortletRequest portletRequest, PortletResponse portletResponse)
84          throws IllegalStateException, IOException, PortletException {
85  
86          HttpServletResponse response = PortalUtil.getHttpServletResponse(
87              portletResponse);
88  
89          if (response.isCommitted()) {
90              throw new IllegalStateException("Response is already committed");
91          }
92  
93          try {
94              dispatch(portletRequest, portletResponse, false, false);
95          }
96          catch (ServletException se) {
97              _log.error(se, se);
98  
99              throw new PortletException(se);
100         }
101     }
102 
103     public void include(
104             PortletRequest portletRequest, PortletResponse portletResponse)
105         throws IOException, PortletException {
106 
107         try {
108             dispatch(portletRequest, portletResponse, false, true);
109         }
110         catch (ServletException se) {
111             _log.error(se, se);
112 
113             throw new PortletException(se);
114         }
115     }
116 
117     public void include(
118             PortletRequest portletRequest, PortletResponse portletResponse,
119             boolean strutsURLEncoder)
120         throws IOException, PortletException {
121 
122         try {
123             dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
124         }
125         catch (ServletException se) {
126             _log.error(se, se);
127 
128             throw new PortletException(se);
129         }
130     }
131 
132     public void include(
133             RenderRequest renderRequest, RenderResponse renderResponse)
134         throws IOException, PortletException {
135 
136         try {
137             dispatch(renderRequest, renderResponse, false, true);
138         }
139         catch (ServletException se) {
140             _log.error(se, se);
141 
142             throw new PortletException(se);
143         }
144     }
145 
146     protected void dispatch(
147             PortletRequest portletRequest, PortletResponse portletResponse,
148             boolean strutsURLEncoder, boolean include)
149         throws IOException, ServletException {
150 
151         if (!include) {
152             if (portletResponse instanceof MimeResponseImpl) {
153                 MimeResponseImpl mimeResponseImpl =
154                     (MimeResponseImpl)portletResponse;
155 
156                 if (mimeResponseImpl.isCalledFlushBuffer()) {
157                     throw new IllegalStateException();
158                 }
159             }
160         }
161 
162         PortletRequestImpl portletRequestImpl =
163             PortletRequestImpl.getPortletRequestImpl(portletRequest);
164         PortletResponseImpl portletResponseImpl =
165             PortletResponseImpl.getPortletResponseImpl(portletResponse);
166 
167         HttpServletRequest request = PortalUtil.getHttpServletRequest(
168             portletRequest);
169         HttpServletResponse response = PortalUtil.getHttpServletResponse(
170             portletResponse);
171 
172         request.setAttribute(
173             JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest);
174         request.setAttribute(
175             JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse);
176 
177         String pathInfo = null;
178         String queryString = null;
179         String requestURI = null;
180         String servletPath = null;
181 
182         if (_path != null) {
183             /*if (ServerDetector.isJetty()) {
184                 int pos = _path.indexOf(StringPool.QUESTION);
185 
186                 if (pos != -1) {
187                     _path = _path.substring(0, pos);
188                 }
189             }*/
190 
191             String pathNoQueryString = _path;
192 
193             int pos = _path.indexOf(CharPool.QUESTION);
194 
195             if (pos != -1) {
196                 pathNoQueryString = _path.substring(0, pos);
197                 queryString = _path.substring(pos + 1, _path.length());
198 
199                 Map<String, String[]> queryParams =
200                     new HashMap<String, String[]>();
201 
202                 String[] queryParamsArray = StringUtil.split(
203                     queryString, StringPool.AMPERSAND);
204 
205                 for (int i = 0; i < queryParamsArray.length; i++) {
206                     String[] nameValuePair = StringUtil.split(
207                         queryParamsArray[i], StringPool.EQUAL);
208 
209                     String name = nameValuePair[0];
210                     String value = StringPool.BLANK;
211 
212                     if (nameValuePair.length == 2) {
213                         value = nameValuePair[1];
214                     }
215 
216                     String[] values = queryParams.get(name);
217 
218                     if (values == null) {
219                         queryParams.put(name, new String[] {value});
220                     }
221                     else {
222                         String[] newValues = new String[values.length + 1];
223 
224                         System.arraycopy(
225                             values, 0, newValues, 0, values.length);
226 
227                         newValues[newValues.length - 1] = value;
228 
229                         queryParams.put(name, newValues);
230                     }
231                 }
232 
233                 DynamicServletRequest dynamicRequest = null;
234 
235                 if (portletRequestImpl.isPrivateRequestAttributes()) {
236                     String portletNamespace = PortalUtil.getPortletNamespace(
237                         portletRequestImpl.getPortletName());
238 
239                     dynamicRequest = new NamespaceServletRequest(
240                         request, portletNamespace, portletNamespace);
241                 }
242                 else {
243                     dynamicRequest = new DynamicServletRequest(request);
244                 }
245 
246                 for (Map.Entry<String, String[]> entry :
247                         queryParams.entrySet()) {
248 
249                     String name = entry.getKey();
250                     String[] values = entry.getValue();
251 
252                     String[] oldValues = dynamicRequest.getParameterValues(
253                         name);
254 
255                     if (oldValues == null) {
256                         dynamicRequest.setParameterValues(name, values);
257                     }
258                     else {
259                         String[] newValues = ArrayUtil.append(
260                             values, oldValues);
261 
262                         dynamicRequest.setParameterValues(name, newValues);
263                     }
264                 }
265 
266                 request = dynamicRequest;
267             }
268 
269             Portlet portlet = portletRequestImpl.getPortlet();
270 
271             PortletApp portletApp = portlet.getPortletApp();
272 
273             Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
274 
275             for (String urlPattern : servletURLPatterns) {
276                 if (urlPattern.endsWith("/*")) {
277                     pos = urlPattern.indexOf("/*");
278 
279                     urlPattern = urlPattern.substring(0, pos);
280 
281                     if (pathNoQueryString.startsWith(urlPattern)) {
282                         pathInfo = pathNoQueryString.substring(
283                             urlPattern.length());
284                         servletPath = urlPattern;
285 
286                         break;
287                     }
288                 }
289             }
290 
291             if ((pathInfo == null) && (servletPath == null)) {
292                 pathInfo = pathNoQueryString;
293                 servletPath = pathNoQueryString;
294             }
295 
296             requestURI = portletRequest.getContextPath() + pathNoQueryString;
297         }
298 
299         PortletServletRequest portletServletRequest = new PortletServletRequest(
300             request, portletRequestImpl, pathInfo, queryString, requestURI,
301             servletPath, _named, include);
302 
303         PortletServletResponse portletServletResponse =
304             new PortletServletResponse(response, portletResponseImpl, 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)_portletContextImpl.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 RequestDispatcher _requestDispatcher;
340     private boolean _named;
341     private Portlet _portlet;
342     private PortletContextImpl _portletContextImpl;
343     private String _path;
344 
345 }