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