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