1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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  public class PortletRequestDispatcherImpl implements PortletRequestDispatcher {
69  
70      public PortletRequestDispatcherImpl(
71          RequestDispatcher requestDispatcher, boolean named,
72          PortletContextImpl portletContextImpl) {
73  
74          this(requestDispatcher, named, portletContextImpl, null);
75      }
76  
77      public PortletRequestDispatcherImpl(
78          RequestDispatcher requestDispatcher, boolean named,
79          PortletContextImpl portletContextImpl, String path) {
80  
81          _requestDispatcher = requestDispatcher;
82          _named = named;
83          _portlet = portletContextImpl.getPortlet();
84          _portletContextImpl = portletContextImpl;
85          _path = path;
86      }
87  
88      public void forward(
89              PortletRequest portletRequest, PortletResponse portletResponse)
90          throws IllegalStateException, IOException, PortletException {
91  
92          HttpServletResponse response = PortalUtil.getHttpServletResponse(
93              portletResponse);
94  
95          if (response.isCommitted()) {
96              throw new IllegalStateException("Response is already committed");
97          }
98  
99          try {
100             dispatch(portletRequest, portletResponse, false, false);
101         }
102         catch (ServletException se) {
103             _log.error(se, se);
104 
105             throw new PortletException(se);
106         }
107     }
108 
109     public void include(
110             PortletRequest portletRequest, PortletResponse portletResponse)
111         throws IOException, PortletException {
112 
113         try {
114             dispatch(portletRequest, portletResponse, false, true);
115         }
116         catch (ServletException se) {
117             _log.error(se, se);
118 
119             throw new PortletException(se);
120         }
121     }
122 
123     public void include(
124             PortletRequest portletRequest, PortletResponse portletResponse,
125             boolean strutsURLEncoder)
126         throws IOException, PortletException {
127 
128         try {
129             dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
130         }
131         catch (ServletException se) {
132             _log.error(se, se);
133 
134             throw new PortletException(se);
135         }
136     }
137 
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)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         String pathInfo = null;
179         String queryString = null;
180         String requestURI = null;
181         String servletPath = null;
182 
183         if (_path != null) {
184             /*if (ServerDetector.isJetty()) {
185                 int pos = _path.indexOf(StringPool.QUESTION);
186 
187                 if (pos != -1) {
188                     _path = _path.substring(0, pos);
189                 }
190             }*/
191 
192             String pathNoQueryString = _path;
193 
194             int pos = _path.indexOf(StringPool.QUESTION);
195 
196             if (pos != -1) {
197                 pathNoQueryString = _path.substring(0, pos);
198                 queryString = _path.substring(pos + 1, _path.length());
199 
200                 Map<String, String[]> queryParams =
201                     new HashMap<String, String[]>();
202 
203                 String[] queryParamsArray = StringUtil.split(
204                     queryString, StringPool.AMPERSAND);
205 
206                 for (int i = 0; i < queryParamsArray.length; i++) {
207                     String[] nameValuePair = StringUtil.split(
208                         queryParamsArray[i], StringPool.EQUAL);
209 
210                     String name = nameValuePair[0];
211                     String value = StringPool.BLANK;
212 
213                     if (nameValuePair.length == 2) {
214                         value = nameValuePair[1];
215                     }
216 
217                     String[] values = queryParams.get(name);
218 
219                     if (values == null) {
220                         queryParams.put(name, new String[] {value});
221                     }
222                     else {
223                         String[] newValues = new String[values.length + 1];
224 
225                         System.arraycopy(
226                             values, 0, newValues, 0, values.length);
227 
228                         newValues[newValues.length - 1] = value;
229 
230                         queryParams.put(name, newValues);
231                     }
232                 }
233 
234                 DynamicServletRequest dynamicRequest = null;
235 
236                 if (portletRequestImpl.isPrivateRequestAttributes()) {
237                     String portletNamespace = PortalUtil.getPortletNamespace(
238                         portletRequestImpl.getPortletName());
239 
240                     dynamicRequest = new NamespaceServletRequest(
241                         request, portletNamespace, portletNamespace);
242                 }
243                 else {
244                     dynamicRequest = new DynamicServletRequest(request);
245                 }
246 
247                 for (Map.Entry<String, String[]> entry :
248                         queryParams.entrySet()) {
249 
250                     String name = entry.getKey();
251                     String[] values = entry.getValue();
252 
253                     String[] oldValues = dynamicRequest.getParameterValues(
254                         name);
255 
256                     if (oldValues == null) {
257                         dynamicRequest.setParameterValues(name, values);
258                     }
259                     else {
260                         String[] newValues = ArrayUtil.append(
261                             values, oldValues);
262 
263                         dynamicRequest.setParameterValues(name, newValues);
264                     }
265                 }
266 
267                 request = dynamicRequest;
268             }
269 
270             Portlet portlet = portletRequestImpl.getPortlet();
271 
272             PortletApp portletApp = portlet.getPortletApp();
273 
274             Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
275 
276             for (String urlPattern : servletURLPatterns) {
277                 if (urlPattern.endsWith("/*")) {
278                     pos = urlPattern.indexOf("/*");
279 
280                     urlPattern = urlPattern.substring(0, pos);
281 
282                     if (pathNoQueryString.startsWith(urlPattern)) {
283                         pathInfo = pathNoQueryString.substring(
284                             urlPattern.length());
285                         servletPath = urlPattern;
286 
287                         break;
288                     }
289                 }
290             }
291 
292             if ((pathInfo == null) && (servletPath == null)) {
293                 pathInfo = pathNoQueryString;
294                 servletPath = pathNoQueryString;
295             }
296 
297             requestURI = portletRequest.getContextPath() + pathNoQueryString;
298         }
299 
300         PortletServletRequest portletServletRequest = new PortletServletRequest(
301             request, portletRequestImpl, pathInfo, queryString, requestURI,
302             servletPath, _named, include);
303 
304         PortletServletResponse portletServletResponse =
305             new PortletServletResponse(response, portletResponseImpl, include);
306 
307         URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
308 
309         if (urlEncoder != null) {
310             portletResponseImpl.setURLEncoder(urlEncoder);
311         }
312         else if (strutsURLEncoder) {
313             ThemeDisplay themeDisplay =
314                 (ThemeDisplay)portletRequest.getAttribute(
315                     WebKeys.THEME_DISPLAY);
316 
317             URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
318                 portletServletRequest.getContextPath(),
319                 themeDisplay.getPathMain(),
320                 (String)_portletContextImpl.getAttribute(
321                     Globals.SERVLET_KEY),
322                 (LiferayPortletURL)portletResponseImpl.createRenderURL());
323 
324             portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
325         }
326 
327         if (include) {
328             _requestDispatcher.include(
329                 portletServletRequest, portletServletResponse);
330         }
331         else {
332             _requestDispatcher.forward(
333                 portletServletRequest, portletServletResponse);
334         }
335     }
336 
337     private static Log _log =
338         LogFactoryUtil.getLog(PortletRequestDispatcherImpl.class);
339 
340     private RequestDispatcher _requestDispatcher;
341     private boolean _named;
342     private Portlet _portlet;
343     private PortletContextImpl _portletContextImpl;
344     private String _path;
345 
346 }