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 
181                         String name = nameValuePair[0];
182                         String value = StringPool.BLANK;
183 
184                         if (nameValuePair.length == 2) {
185                             value = nameValuePair[1];
186                         }
187 
188                         String[] values = queryParams.get(name);
189 
190                         if (values == null) {
191                             queryParams.put(name, new String[] {value});
192                         }
193                         else {
194                             String[] newValues = new String[values.length + 1];
195 
196                             System.arraycopy(
197                                 values, 0, newValues, 0, values.length);
198 
199                             newValues[newValues.length - 1] = value;
200 
201                             queryParams.put(name, newValues);
202                         }
203                     }
204 
205                     DynamicServletRequest dynamicRequest = null;
206 
207                     if (portletRequestImpl.isPrivateRequestAttributes()) {
208                         String portletNamespace =
209                             PortalUtil.getPortletNamespace(
210                                 portletRequestImpl.getPortletName());
211 
212                         dynamicRequest = new NamespaceServletRequest(
213                             request, portletNamespace, portletNamespace);
214                     }
215                     else {
216                         dynamicRequest = new DynamicServletRequest(request);
217                     }
218 
219                     for (Map.Entry<String, String[]> entry :
220                             queryParams.entrySet()) {
221 
222                         String name = entry.getKey();
223                         String[] values = entry.getValue();
224 
225                         String[] oldValues =
226                             dynamicRequest.getParameterValues(name);
227 
228                         if (oldValues == null) {
229                             dynamicRequest.setParameterValues(name, values);
230                         }
231                         else {
232                             String[] newValues = ArrayUtil.append(
233                                 values, oldValues);
234 
235                             dynamicRequest.setParameterValues(name, newValues);
236                         }
237                     }
238 
239                     request = dynamicRequest;
240                 }
241 
242                 Portlet portlet = portletRequestImpl.getPortlet();
243 
244                 PortletApp portletApp = portlet.getPortletApp();
245 
246                 Set<String> servletURLPatterns =
247                     portletApp.getServletURLPatterns();
248 
249                 for (String urlPattern : servletURLPatterns) {
250                     if (urlPattern.endsWith("/*")) {
251                         pos = urlPattern.indexOf("/*");
252 
253                         urlPattern = urlPattern.substring(0, pos);
254 
255                         if (pathNoQueryString.startsWith(urlPattern)) {
256                             pathInfo = pathNoQueryString.substring(
257                                 urlPattern.length());
258                             servletPath = urlPattern;
259 
260                             break;
261                         }
262                     }
263                 }
264 
265                 if ((pathInfo == null) && (servletPath == null)) {
266                     pathInfo = pathNoQueryString;
267                     servletPath = pathNoQueryString;
268                 }
269 
270                 requestURI =
271                     portletRequest.getContextPath() + pathNoQueryString;
272             }
273 
274             PortletServletRequest portletServletRequest =
275                 new PortletServletRequest(
276                     request, portletRequestImpl, pathInfo, queryString,
277                     requestURI, servletPath, _named, include);
278 
279             PortletServletResponse portletServletResponse =
280                 new PortletServletResponse(
281                     response, portletResponseImpl, include);
282 
283             URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
284 
285             if (urlEncoder != null) {
286                 portletResponseImpl.setURLEncoder(urlEncoder);
287             }
288             else if (strutsURLEncoder) {
289                 ThemeDisplay themeDisplay =
290                     (ThemeDisplay)portletRequest.getAttribute(
291                         WebKeys.THEME_DISPLAY);
292 
293                 URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
294                     portletServletRequest.getContextPath(),
295                     themeDisplay.getPathMain(),
296                     (String)_portletContextImpl.getAttribute(
297                         Globals.SERVLET_KEY),
298                     (LiferayPortletURL)portletResponseImpl.createRenderURL());
299 
300                 portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
301             }
302 
303             if (include) {
304                 _requestDispatcher.include(
305                     portletServletRequest, portletServletResponse);
306             }
307             else {
308                 _requestDispatcher.forward(
309                     portletServletRequest, portletServletResponse);
310             }
311         }
312         catch (ServletException se) {
313             _log.error(se, se);
314 
315             throw new PortletException(se);
316         }
317     }
318 
319     private static Log _log =
320         LogFactoryUtil.getLog(PortletRequestDispatcherImpl.class);
321 
322     private RequestDispatcher _requestDispatcher;
323     private boolean _named;
324     private Portlet _portlet;
325     private PortletContextImpl _portletContextImpl;
326     private String _path;
327 
328 }