001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
020    import com.liferay.portal.kernel.servlet.URLEncoder;
021    import com.liferay.portal.kernel.util.ArrayUtil;
022    import com.liferay.portal.kernel.util.CharPool;
023    import com.liferay.portal.kernel.util.JavaConstants;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.model.Portlet;
027    import com.liferay.portal.model.PortletApp;
028    import com.liferay.portal.servlet.NamespaceServletRequest;
029    import com.liferay.portal.struts.StrutsURLEncoder;
030    import com.liferay.portal.theme.ThemeDisplay;
031    import com.liferay.portal.util.PortalUtil;
032    import com.liferay.portal.util.WebKeys;
033    import com.liferay.util.servlet.DynamicServletRequest;
034    
035    import java.io.IOException;
036    
037    import java.util.HashMap;
038    import java.util.Map;
039    import java.util.Set;
040    
041    import javax.portlet.PortletException;
042    import javax.portlet.PortletRequest;
043    import javax.portlet.PortletRequestDispatcher;
044    import javax.portlet.PortletResponse;
045    import javax.portlet.RenderRequest;
046    import javax.portlet.RenderResponse;
047    
048    import javax.servlet.RequestDispatcher;
049    import javax.servlet.ServletException;
050    import javax.servlet.http.HttpServletRequest;
051    import javax.servlet.http.HttpServletResponse;
052    
053    import org.apache.struts.Globals;
054    
055    /**
056     * @author Brian Wing Shun Chan
057     * @author Brian Myunghun Kim
058     */
059    public class PortletRequestDispatcherImpl implements PortletRequestDispatcher {
060    
061            public PortletRequestDispatcherImpl(
062                    RequestDispatcher requestDispatcher, boolean named,
063                    PortletContextImpl portletContextImpl) {
064    
065                    this(requestDispatcher, named, portletContextImpl, null);
066            }
067    
068            public PortletRequestDispatcherImpl(
069                    RequestDispatcher requestDispatcher, boolean named,
070                    PortletContextImpl portletContextImpl, String path) {
071    
072                    _requestDispatcher = requestDispatcher;
073                    _named = named;
074                    _portlet = portletContextImpl.getPortlet();
075                    _portletContextImpl = portletContextImpl;
076                    _path = path;
077            }
078    
079            public void forward(
080                            PortletRequest portletRequest, PortletResponse portletResponse)
081                    throws IllegalStateException, IOException, PortletException {
082    
083                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
084                            portletResponse);
085    
086                    if (response.isCommitted()) {
087                            throw new IllegalStateException("Response is already committed");
088                    }
089    
090                    try {
091                            dispatch(portletRequest, portletResponse, false, false);
092                    }
093                    catch (ServletException se) {
094                            _log.error(se, se);
095    
096                            throw new PortletException(se);
097                    }
098            }
099    
100            public void include(
101                            PortletRequest portletRequest, PortletResponse portletResponse)
102                    throws IOException, PortletException {
103    
104                    try {
105                            dispatch(portletRequest, portletResponse, false, true);
106                    }
107                    catch (ServletException se) {
108                            _log.error(se, se);
109    
110                            throw new PortletException(se);
111                    }
112            }
113    
114            public void include(
115                            PortletRequest portletRequest, PortletResponse portletResponse,
116                            boolean strutsURLEncoder)
117                    throws IOException, PortletException {
118    
119                    try {
120                            dispatch(portletRequest, portletResponse, strutsURLEncoder, true);
121                    }
122                    catch (ServletException se) {
123                            _log.error(se, se);
124    
125                            throw new PortletException(se);
126                    }
127            }
128    
129            public void include(
130                            RenderRequest renderRequest, RenderResponse renderResponse)
131                    throws IOException, PortletException {
132    
133                    try {
134                            dispatch(renderRequest, renderResponse, false, true);
135                    }
136                    catch (ServletException se) {
137                            _log.error(se, se);
138    
139                            throw new PortletException(se);
140                    }
141            }
142    
143            protected void dispatch(
144                            PortletRequest portletRequest, PortletResponse portletResponse,
145                            boolean strutsURLEncoder, boolean include)
146                    throws IOException, ServletException {
147    
148                    if (!include) {
149                            if (portletResponse instanceof MimeResponseImpl) {
150                                    MimeResponseImpl mimeResponseImpl =
151                                            (MimeResponseImpl)portletResponse;
152    
153                                    if (mimeResponseImpl.isCalledFlushBuffer()) {
154                                            throw new IllegalStateException();
155                                    }
156                            }
157                    }
158    
159                    PortletRequestImpl portletRequestImpl =
160                            PortletRequestImpl.getPortletRequestImpl(portletRequest);
161                    PortletResponseImpl portletResponseImpl =
162                            PortletResponseImpl.getPortletResponseImpl(portletResponse);
163    
164                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
165                            portletRequest);
166                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
167                            portletResponse);
168    
169                    request.setAttribute(
170                            JavaConstants.JAVAX_PORTLET_REQUEST, portletRequest);
171                    request.setAttribute(
172                            JavaConstants.JAVAX_PORTLET_RESPONSE, portletResponse);
173    
174                    String pathInfo = null;
175                    String queryString = null;
176                    String requestURI = null;
177                    String servletPath = null;
178    
179                    if (_path != null) {
180                            String pathNoQueryString = _path;
181    
182                            int pos = _path.indexOf(CharPool.QUESTION);
183    
184                            if (pos != -1) {
185                                    pathNoQueryString = _path.substring(0, pos);
186                                    queryString = _path.substring(pos + 1, _path.length());
187    
188                                    Map<String, String[]> queryParams =
189                                            new HashMap<String, String[]>();
190    
191                                    String[] queryParamsArray = StringUtil.split(
192                                            queryString, StringPool.AMPERSAND);
193    
194                                    for (int i = 0; i < queryParamsArray.length; i++) {
195                                            String[] nameValuePair = StringUtil.split(
196                                                    queryParamsArray[i], StringPool.EQUAL);
197    
198                                            String name = nameValuePair[0];
199                                            String value = StringPool.BLANK;
200    
201                                            if (nameValuePair.length == 2) {
202                                                    value = nameValuePair[1];
203                                            }
204    
205                                            String[] values = queryParams.get(name);
206    
207                                            if (values == null) {
208                                                    queryParams.put(name, new String[] {value});
209                                            }
210                                            else {
211                                                    String[] newValues = new String[values.length + 1];
212    
213                                                    System.arraycopy(
214                                                            values, 0, newValues, 0, values.length);
215    
216                                                    newValues[newValues.length - 1] = value;
217    
218                                                    queryParams.put(name, newValues);
219                                            }
220                                    }
221    
222                                    DynamicServletRequest dynamicRequest = null;
223    
224                                    if (portletRequestImpl.isPrivateRequestAttributes()) {
225                                            String portletNamespace = PortalUtil.getPortletNamespace(
226                                                    portletRequestImpl.getPortletName());
227    
228                                            dynamicRequest = new NamespaceServletRequest(
229                                                    request, portletNamespace, portletNamespace);
230                                    }
231                                    else {
232                                            dynamicRequest = new DynamicServletRequest(request);
233                                    }
234    
235                                    for (Map.Entry<String, String[]> entry :
236                                                    queryParams.entrySet()) {
237    
238                                            String name = entry.getKey();
239                                            String[] values = entry.getValue();
240    
241                                            String[] oldValues = dynamicRequest.getParameterValues(
242                                                    name);
243    
244                                            if (oldValues == null) {
245                                                    dynamicRequest.setParameterValues(name, values);
246                                            }
247                                            else {
248                                                    String[] newValues = ArrayUtil.append(
249                                                            values, oldValues);
250    
251                                                    dynamicRequest.setParameterValues(name, newValues);
252                                            }
253                                    }
254    
255                                    request = dynamicRequest;
256                            }
257    
258                            Portlet portlet = portletRequestImpl.getPortlet();
259    
260                            PortletApp portletApp = portlet.getPortletApp();
261    
262                            Set<String> servletURLPatterns = portletApp.getServletURLPatterns();
263    
264                            for (String urlPattern : servletURLPatterns) {
265                                    if (urlPattern.endsWith("/*")) {
266                                            pos = urlPattern.indexOf("/*");
267    
268                                            urlPattern = urlPattern.substring(0, pos);
269    
270                                            if (pathNoQueryString.startsWith(urlPattern)) {
271                                                    pathInfo = pathNoQueryString.substring(
272                                                            urlPattern.length());
273                                                    servletPath = urlPattern;
274    
275                                                    break;
276                                            }
277                                    }
278                            }
279    
280                            if ((pathInfo == null) && (servletPath == null)) {
281                                    pathInfo = pathNoQueryString;
282                                    servletPath = pathNoQueryString;
283                            }
284    
285                            requestURI = portletRequest.getContextPath() + pathNoQueryString;
286                    }
287    
288                    PortletServletRequest portletServletRequest = new PortletServletRequest(
289                            request, portletRequestImpl, pathInfo, queryString, requestURI,
290                            servletPath, _named, include);
291    
292                    PortletServletResponse portletServletResponse =
293                            new PortletServletResponse(response, portletResponseImpl, include);
294    
295                    URLEncoder urlEncoder = _portlet.getURLEncoderInstance();
296    
297                    if (urlEncoder != null) {
298                            portletResponseImpl.setURLEncoder(urlEncoder);
299                    }
300                    else if (strutsURLEncoder) {
301                            ThemeDisplay themeDisplay =
302                                    (ThemeDisplay)portletRequest.getAttribute(
303                                            WebKeys.THEME_DISPLAY);
304    
305                            URLEncoder strutsURLEncoderObj = new StrutsURLEncoder(
306                                    portletServletRequest.getContextPath(),
307                                    themeDisplay.getPathMain(),
308                                    (String)_portletContextImpl.getAttribute(
309                                            Globals.SERVLET_KEY),
310                                    (LiferayPortletURL)portletResponseImpl.createRenderURL());
311    
312                            portletResponseImpl.setURLEncoder(strutsURLEncoderObj);
313                    }
314    
315                    if (include) {
316                            _requestDispatcher.include(
317                                    portletServletRequest, portletServletResponse);
318                    }
319                    else {
320                            _requestDispatcher.forward(
321                                    portletServletRequest, portletServletResponse);
322                    }
323            }
324    
325            private static Log _log = LogFactoryUtil.getLog(
326                    PortletRequestDispatcherImpl.class);
327    
328            private RequestDispatcher _requestDispatcher;
329            private boolean _named;
330            private Portlet _portlet;
331            private PortletContextImpl _portletContextImpl;
332            private String _path;
333    
334    }