1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.portal.action;
24  
25  import com.liferay.portal.kernel.language.LanguageUtil;
26  import com.liferay.portal.kernel.servlet.BrowserSniffer;
27  import com.liferay.portal.kernel.servlet.HttpHeaders;
28  import com.liferay.portal.kernel.servlet.StringServletResponse;
29  import com.liferay.portal.kernel.util.ContentTypes;
30  import com.liferay.portal.kernel.util.JavaConstants;
31  import com.liferay.portal.kernel.util.ParamUtil;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.model.Layout;
34  import com.liferay.portal.model.Portlet;
35  import com.liferay.portal.model.PortletPreferencesIds;
36  import com.liferay.portal.model.User;
37  import com.liferay.portal.model.impl.LayoutImpl;
38  import com.liferay.portal.service.PortletLocalServiceUtil;
39  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
40  import com.liferay.portal.struts.ActionConstants;
41  import com.liferay.portal.struts.StrutsUtil;
42  import com.liferay.portal.theme.ThemeDisplay;
43  import com.liferay.portal.util.PortalUtil;
44  import com.liferay.portal.util.WebKeys;
45  import com.liferay.portlet.ActionRequestFactory;
46  import com.liferay.portlet.ActionRequestImpl;
47  import com.liferay.portlet.ActionResponseFactory;
48  import com.liferay.portlet.ActionResponseImpl;
49  import com.liferay.portlet.CachePortlet;
50  import com.liferay.portlet.PortletConfigFactory;
51  import com.liferay.portlet.PortletInstanceFactory;
52  import com.liferay.portlet.PortletPreferencesFactoryUtil;
53  import com.liferay.portlet.PortletURLImpl;
54  import com.liferay.portlet.RenderParametersPool;
55  import com.liferay.util.Http;
56  import com.liferay.util.servlet.UploadServletRequest;
57  
58  import java.util.Iterator;
59  import java.util.Map;
60  
61  import javax.portlet.PortletConfig;
62  import javax.portlet.PortletContext;
63  import javax.portlet.PortletMode;
64  import javax.portlet.PortletPreferences;
65  import javax.portlet.PortletURL;
66  import javax.portlet.WindowState;
67  
68  import javax.servlet.RequestDispatcher;
69  import javax.servlet.ServletContext;
70  import javax.servlet.http.HttpServletRequest;
71  import javax.servlet.http.HttpServletResponse;
72  import javax.servlet.http.HttpSession;
73  import javax.servlet.jsp.PageContext;
74  
75  import org.apache.commons.logging.Log;
76  import org.apache.commons.logging.LogFactory;
77  import org.apache.struts.action.Action;
78  import org.apache.struts.action.ActionForm;
79  import org.apache.struts.action.ActionForward;
80  import org.apache.struts.action.ActionMapping;
81  
82  /**
83   * <a href="LayoutAction.java.html"><b><i>View Source</i></b></a>
84   *
85   * @author Brian Wing Shun Chan
86   *
87   */
88  public class LayoutAction extends Action {
89  
90      public ActionForward execute(
91              ActionMapping mapping, ActionForm form, HttpServletRequest req,
92              HttpServletResponse res)
93          throws Exception {
94  
95          ThemeDisplay themeDisplay =
96              (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
97  
98          Layout layout = themeDisplay.getLayout();
99  
100         Boolean layoutDefault  = (Boolean)req.getAttribute(
101             WebKeys.LAYOUT_DEFAULT);
102 
103         if ((layoutDefault != null) && (layoutDefault.booleanValue())) {
104             Layout requestedLayout =
105                 (Layout)req.getAttribute(WebKeys.REQUESTED_LAYOUT);
106 
107             if (requestedLayout != null) {
108                 String redirect =
109                     themeDisplay.getURLSignIn() + "?redirect=" +
110                         PortalUtil.getLayoutURL(requestedLayout, themeDisplay);
111 
112                 if (_log.isDebugEnabled()) {
113                     _log.debug("Redirect requested layout to " + redirect);
114                 }
115 
116                 res.sendRedirect(redirect);
117             }
118             else {
119                 String redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
120 
121                 if (_log.isDebugEnabled()) {
122                     _log.debug("Redirect default layout to " + redirect);
123                 }
124 
125                 res.sendRedirect(redirect);
126             }
127 
128             return null;
129         }
130 
131         long plid = ParamUtil.getLong(req, "p_l_id");
132         boolean resetLayout = ParamUtil.getBoolean(
133             req, "p_l_reset", PortalUtil.DEFAULT_P_L_RESET);
134         String action = ParamUtil.getString(req, "p_p_action");
135 
136         if (plid > 0) {
137             try {
138                 if (resetLayout) {
139                     RenderParametersPool.clear(req, plid);
140                 }
141 
142                 if (action.equals("1")) {
143                     Portlet portlet = processActionRequest(req, res);
144 
145                     if (portlet != null) {
146                         ActionResponseImpl actionResponseImpl =
147                             (ActionResponseImpl)req.getAttribute(
148                                 JavaConstants.JAVAX_PORTLET_RESPONSE);
149 
150                         String redirectLocation =
151                             actionResponseImpl.getRedirectLocation();
152 
153                         if (Validator.isNotNull(redirectLocation)) {
154                             res.sendRedirect(redirectLocation);
155 
156                             return null;
157                         }
158 
159                         if (portlet.isActionURLRedirect()) {
160                             redirectActionURL(
161                                 req, res, actionResponseImpl, portlet);
162                         }
163                     }
164                 }
165                 else if (action.equals("0")) {
166                     processRenderRequest(req, res);
167                 }
168 
169                 if (layout != null) {
170 
171                     // Include layout content before the page loads because
172                     // portlets on the page can set the page title and page
173                     // subtitle
174 
175                     includeLayoutContent(req, res, themeDisplay, layout);
176                 }
177 
178                 return mapping.findForward("portal.layout");
179             }
180             catch (Exception e) {
181                 req.setAttribute(PageContext.EXCEPTION, e);
182 
183                 return mapping.findForward(ActionConstants.COMMON_ERROR);
184             }
185             finally {
186                 try {
187                     if (action.equals("1")) {
188                         ActionRequestImpl actionRequestImpl =
189                             (ActionRequestImpl)req.getAttribute(
190                                 JavaConstants.JAVAX_PORTLET_REQUEST);
191 
192                         ActionRequestFactory.recycle(actionRequestImpl);
193                     }
194                 }
195                 catch (Exception e) {
196                     _log.error(e);
197                 }
198 
199                 req.removeAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
200 
201                 try {
202                     if (action.equals("1")) {
203                         ActionResponseImpl actionResponseImpl =
204                             (ActionResponseImpl)req.getAttribute(
205                                 JavaConstants.JAVAX_PORTLET_RESPONSE);
206 
207                         ActionResponseFactory.recycle(actionResponseImpl);
208                     }
209                 }
210                 catch (Exception e) {
211                     _log.error(e);
212                 }
213 
214                 req.removeAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
215             }
216         }
217         else {
218             try {
219                 forwardLayout(req);
220 
221                 return mapping.findForward(ActionConstants.COMMON_FORWARD);
222             }
223             catch (Exception e) {
224                 req.setAttribute(PageContext.EXCEPTION, e);
225 
226                 return mapping.findForward(ActionConstants.COMMON_ERROR);
227             }
228         }
229     }
230 
231     protected void forwardLayout(HttpServletRequest req) throws Exception {
232         Layout layout = (Layout)req.getAttribute(WebKeys.LAYOUT);
233         long plid = LayoutImpl.DEFAULT_PLID;
234         String layoutFriendlyURL = null;
235 
236         ThemeDisplay themeDisplay =
237             (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
238 
239         if (layout != null) {
240             plid = layout.getPlid();
241             layoutFriendlyURL =
242                 PortalUtil.getLayoutFriendlyURL(layout, themeDisplay);
243         }
244 
245         String forwardURL = layoutFriendlyURL;
246 
247         if (Validator.isNull(forwardURL)) {
248             forwardURL =
249                 themeDisplay.getPathMain() + "/portal/layout?p_l_id=" + plid;
250 
251             if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
252                 forwardURL = Http.addParameter(
253                     forwardURL, "doAsUserId", themeDisplay.getDoAsUserId());
254             }
255         }
256 
257         if (_log.isDebugEnabled()) {
258             _log.debug("Forward layout to " + forwardURL);
259         }
260 
261         req.setAttribute(WebKeys.FORWARD_URL, forwardURL);
262     }
263 
264     protected void includeLayoutContent(
265             HttpServletRequest req, HttpServletResponse res,
266             ThemeDisplay themeDisplay, Layout layout)
267         throws Exception {
268 
269         ServletContext ctx = (ServletContext)req.getAttribute(WebKeys.CTX);
270 
271         String path = StrutsUtil.TEXT_HTML_DIR;
272 
273         if (BrowserSniffer.is_wap_xhtml(req)) {
274             path = StrutsUtil.TEXT_WAP_DIR;
275         }
276 
277         // Manually check the p_p_id. See LEP-1724.
278 
279         if (themeDisplay.isStateExclusive() ||
280             Validator.isNotNull(ParamUtil.getString(req, "p_p_id"))) {
281 
282             path += "/portal/layout/view/portlet.jsp";
283         }
284         else {
285             path += PortalUtil.getLayoutViewPage(layout);
286         }
287 
288         RequestDispatcher rd = ctx.getRequestDispatcher(path);
289 
290         StringServletResponse stringServletRes = new StringServletResponse(res);
291 
292         rd.include(req, stringServletRes);
293 
294         req.setAttribute(WebKeys.LAYOUT_CONTENT, stringServletRes.getString());
295     }
296 
297     protected Portlet processActionRequest(
298             HttpServletRequest req, HttpServletResponse res)
299         throws Exception {
300 
301         return processPortletRequest(req, res, true);
302     }
303 
304     protected Portlet processPortletRequest(
305             HttpServletRequest req, HttpServletResponse res, boolean action)
306         throws Exception {
307 
308         HttpSession ses = req.getSession();
309 
310         long companyId = PortalUtil.getCompanyId(req);
311         User user = PortalUtil.getUser(req);
312         Layout layout = (Layout)req.getAttribute(WebKeys.LAYOUT);
313         String portletId = ParamUtil.getString(req, "p_p_id");
314 
315         Portlet portlet = PortletLocalServiceUtil.getPortletById(
316             companyId, portletId);
317 
318         if (portlet == null) {
319             return null;
320         }
321 
322         ServletContext ctx = (ServletContext)req.getAttribute(WebKeys.CTX);
323 
324         CachePortlet cachePortlet = PortletInstanceFactory.create(portlet, ctx);
325 
326         if (user != null) {
327             CachePortlet.clearResponse(
328                 ses, layout.getPrimaryKey(), portletId,
329                 LanguageUtil.getLanguageId(req));
330         }
331 
332         PortletPreferencesIds portletPreferencesIds =
333             PortletPreferencesFactoryUtil.getPortletPreferencesIds(
334                 req, portletId);
335 
336         PortletPreferences portletPreferences =
337             PortletPreferencesLocalServiceUtil.getPreferences(
338                 portletPreferencesIds);
339 
340         PortletConfig portletConfig = PortletConfigFactory.create(portlet, ctx);
341         PortletContext portletCtx = portletConfig.getPortletContext();
342 
343         WindowState windowState = new WindowState(
344             ParamUtil.getString(req, "p_p_state"));
345 
346         PortletMode portletMode = new PortletMode(
347             ParamUtil.getString(req, "p_p_mode"));
348 
349         if (action) {
350             String contentType = req.getHeader(HttpHeaders.CONTENT_TYPE);
351 
352             if (_log.isDebugEnabled()) {
353                 _log.debug("Content type " + contentType);
354             }
355 
356             UploadServletRequest uploadReq = null;
357 
358             try {
359                 if ((contentType != null) &&
360                     (contentType.startsWith(
361                         ContentTypes.MULTIPART_FORM_DATA))) {
362 
363                     if (!cachePortlet.getPortletConfig().isWARFile() ||
364                         cachePortlet.isStrutsPortlet()) {
365 
366                         uploadReq = new UploadServletRequest(req);
367 
368                         req = uploadReq;
369                     }
370                 }
371 
372                 ActionRequestImpl actionRequestImpl =
373                     ActionRequestFactory.create(
374                         req, portlet, cachePortlet, portletCtx, windowState,
375                         portletMode, portletPreferences, layout.getPlid());
376 
377                 ActionResponseImpl actionResponseImpl =
378                     ActionResponseFactory.create(
379                         actionRequestImpl, res, portletId, user, layout,
380                         windowState, portletMode);
381 
382                 actionRequestImpl.defineObjects(
383                     portletConfig, actionResponseImpl);
384 
385                 cachePortlet.processAction(
386                     actionRequestImpl, actionResponseImpl);
387 
388                 RenderParametersPool.put(
389                     req, layout.getPlid(), portletId,
390                     actionResponseImpl.getRenderParameters());
391             }
392             finally {
393                 if (uploadReq != null) {
394                     uploadReq.cleanUp();
395                 }
396             }
397         }
398         else {
399             PortalUtil.updateWindowState(
400                 portletId, user, layout, windowState, req);
401 
402             PortalUtil.updatePortletMode(
403                 portletId, user, layout, portletMode, req);
404         }
405 
406         return portlet;
407     }
408 
409     protected Portlet processRenderRequest(
410             HttpServletRequest req, HttpServletResponse res)
411         throws Exception {
412 
413         return processPortletRequest(req, res, false);
414     }
415 
416     protected void redirectActionURL(
417             HttpServletRequest req, HttpServletResponse res,
418             ActionResponseImpl actionResponseImpl, Portlet portlet)
419         throws Exception {
420 
421         ActionRequestImpl actionRequestImpl =
422             (ActionRequestImpl)req.getAttribute(
423                 JavaConstants.JAVAX_PORTLET_REQUEST);
424 
425         Layout layout = (Layout)req.getAttribute(WebKeys.LAYOUT);
426 
427         PortletURL portletURL = new PortletURLImpl(
428             actionRequestImpl, actionRequestImpl.getPortletName(),
429             layout.getLayoutId(), false);
430 
431         Map renderParameters = actionResponseImpl.getRenderParameters();
432 
433         Iterator itr = renderParameters.entrySet().iterator();
434 
435         while (itr.hasNext()) {
436             Map.Entry entry = (Map.Entry)itr.next();
437 
438             String key = (String)entry.getKey();
439             Object value = entry.getValue();
440 
441             if (value instanceof String) {
442                 portletURL.setParameter(key, (String)value);
443             }
444             else if (value instanceof String[]) {
445                 portletURL.setParameter(key, (String[])value);
446             }
447         }
448 
449         res.sendRedirect(portletURL.toString());
450     }
451 
452     private static Log _log = LogFactory.getLog(LayoutAction.class);
453 
454 }