001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portal.action;
022:
023: import com.liferay.portal.kernel.language.LanguageUtil;
024: import com.liferay.portal.kernel.servlet.BrowserSniffer;
025: import com.liferay.portal.kernel.servlet.HttpHeaders;
026: import com.liferay.portal.kernel.servlet.StringServletResponse;
027: import com.liferay.portal.kernel.util.ContentTypes;
028: import com.liferay.portal.kernel.util.JavaConstants;
029: import com.liferay.portal.kernel.util.ParamUtil;
030: import com.liferay.portal.kernel.util.StringPool;
031: import com.liferay.portal.kernel.util.Validator;
032: import com.liferay.portal.model.Layout;
033: import com.liferay.portal.model.Portlet;
034: import com.liferay.portal.model.PortletPreferencesIds;
035: import com.liferay.portal.model.User;
036: import com.liferay.portal.model.impl.LayoutImpl;
037: import com.liferay.portal.service.PortletLocalServiceUtil;
038: import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
039: import com.liferay.portal.struts.ActionConstants;
040: import com.liferay.portal.struts.StrutsUtil;
041: import com.liferay.portal.theme.ThemeDisplay;
042: import com.liferay.portal.util.PortalUtil;
043: import com.liferay.portal.util.PropsValues;
044: import com.liferay.portal.util.WebKeys;
045: import com.liferay.portlet.ActionRequestFactory;
046: import com.liferay.portlet.ActionRequestImpl;
047: import com.liferay.portlet.ActionResponseFactory;
048: import com.liferay.portlet.ActionResponseImpl;
049: import com.liferay.portlet.CachePortlet;
050: import com.liferay.portlet.PortletConfigFactory;
051: import com.liferay.portlet.PortletInstanceFactory;
052: import com.liferay.portlet.PortletPreferencesFactoryUtil;
053: import com.liferay.portlet.PortletURLImpl;
054: import com.liferay.portlet.RenderParametersPool;
055: import com.liferay.portlet.RenderRequestFactory;
056: import com.liferay.portlet.RenderRequestImpl;
057: import com.liferay.portlet.RenderResponseFactory;
058: import com.liferay.portlet.RenderResponseImpl;
059: import com.liferay.util.Http;
060: import com.liferay.util.servlet.ServletResponseUtil;
061: import com.liferay.util.servlet.UploadServletRequest;
062:
063: import java.io.ByteArrayInputStream;
064: import java.io.InputStream;
065:
066: import java.util.Iterator;
067: import java.util.Map;
068:
069: import javax.portlet.PortletConfig;
070: import javax.portlet.PortletContext;
071: import javax.portlet.PortletMode;
072: import javax.portlet.PortletPreferences;
073: import javax.portlet.PortletURL;
074: import javax.portlet.WindowState;
075:
076: import javax.servlet.RequestDispatcher;
077: import javax.servlet.ServletContext;
078: import javax.servlet.http.HttpServletRequest;
079: import javax.servlet.http.HttpServletResponse;
080: import javax.servlet.http.HttpSession;
081: import javax.servlet.jsp.PageContext;
082:
083: import org.apache.commons.logging.Log;
084: import org.apache.commons.logging.LogFactory;
085: import org.apache.struts.action.Action;
086: import org.apache.struts.action.ActionForm;
087: import org.apache.struts.action.ActionForward;
088: import org.apache.struts.action.ActionMapping;
089:
090: /**
091: * <a href="LayoutAction.java.html"><b><i>View Source</i></b></a>
092: *
093: * @author Brian Wing Shun Chan
094: *
095: */
096: public class LayoutAction extends Action {
097:
098: public ActionForward execute(ActionMapping mapping,
099: ActionForm form, HttpServletRequest req,
100: HttpServletResponse res) throws Exception {
101:
102: ThemeDisplay themeDisplay = (ThemeDisplay) req
103: .getAttribute(WebKeys.THEME_DISPLAY);
104:
105: Layout layout = themeDisplay.getLayout();
106:
107: Boolean layoutDefault = (Boolean) req
108: .getAttribute(WebKeys.LAYOUT_DEFAULT);
109:
110: if ((layoutDefault != null) && (layoutDefault.booleanValue())) {
111: Layout requestedLayout = (Layout) req
112: .getAttribute(WebKeys.REQUESTED_LAYOUT);
113:
114: if (requestedLayout != null) {
115: String redirect = themeDisplay.getURLSignIn()
116: + "?redirect="
117: + PortalUtil.getLayoutURL(requestedLayout,
118: themeDisplay);
119:
120: if (_log.isDebugEnabled()) {
121: _log.debug("Redirect requested layout to "
122: + redirect);
123: }
124:
125: res.sendRedirect(redirect);
126: } else {
127: String redirect = PortalUtil.getLayoutURL(layout,
128: themeDisplay);
129:
130: if (_log.isDebugEnabled()) {
131: _log
132: .debug("Redirect default layout to "
133: + redirect);
134: }
135:
136: res.sendRedirect(redirect);
137: }
138:
139: return null;
140: }
141:
142: long plid = ParamUtil.getLong(req, "p_l_id");
143: boolean resetLayout = ParamUtil.getBoolean(req, "p_l_reset",
144: PropsValues.LAYOUT_DEFAULT_P_L_RESET);
145: String action = ParamUtil.getString(req, "p_p_action");
146:
147: if (plid > 0) {
148: try {
149: if (resetLayout) {
150: RenderParametersPool.clear(req, plid);
151: }
152:
153: if (action.equals("1")) {
154: Portlet portlet = processActionRequest(req, res);
155:
156: if (portlet != null) {
157: ActionResponseImpl actionResponseImpl = (ActionResponseImpl) req
158: .getAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
159:
160: String redirectLocation = actionResponseImpl
161: .getRedirectLocation();
162:
163: if (Validator.isNotNull(redirectLocation)) {
164: res.sendRedirect(redirectLocation);
165:
166: return null;
167: }
168:
169: if (portlet.isActionURLRedirect()) {
170: redirectActionURL(req, res,
171: actionResponseImpl, portlet);
172: }
173: }
174: } else if (action.equals("0")) {
175: processRenderRequest(req, res);
176: }
177:
178: if (layout != null) {
179:
180: // Include layout content before the page loads because
181: // portlets on the page can set the page title and page
182: // subtitle
183:
184: includeLayoutContent(req, res, themeDisplay, layout);
185:
186: if (themeDisplay.isStateExclusive()) {
187: serverExclusiveResource(req, res, themeDisplay);
188:
189: return null;
190: }
191: }
192:
193: return mapping.findForward("portal.layout");
194: } catch (Exception e) {
195: req.setAttribute(PageContext.EXCEPTION, e);
196:
197: return mapping
198: .findForward(ActionConstants.COMMON_ERROR);
199: } finally {
200: try {
201: if (action.equals("1")) {
202: ActionRequestImpl actionRequestImpl = (ActionRequestImpl) req
203: .getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
204:
205: ActionRequestFactory.recycle(actionRequestImpl);
206: }
207: } catch (Exception e) {
208: _log.error(e);
209: }
210:
211: req
212: .removeAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
213:
214: try {
215: if (action.equals("1")) {
216: ActionResponseImpl actionResponseImpl = (ActionResponseImpl) req
217: .getAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
218:
219: ActionResponseFactory
220: .recycle(actionResponseImpl);
221: }
222: } catch (Exception e) {
223: _log.error(e);
224: }
225:
226: req
227: .removeAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
228: }
229: } else {
230: try {
231: forwardLayout(req);
232:
233: return mapping
234: .findForward(ActionConstants.COMMON_FORWARD);
235: } catch (Exception e) {
236: req.setAttribute(PageContext.EXCEPTION, e);
237:
238: return mapping
239: .findForward(ActionConstants.COMMON_ERROR);
240: }
241: }
242: }
243:
244: protected void forwardLayout(HttpServletRequest req)
245: throws Exception {
246: Layout layout = (Layout) req.getAttribute(WebKeys.LAYOUT);
247: long plid = LayoutImpl.DEFAULT_PLID;
248: String layoutFriendlyURL = null;
249:
250: ThemeDisplay themeDisplay = (ThemeDisplay) req
251: .getAttribute(WebKeys.THEME_DISPLAY);
252:
253: if (layout != null) {
254: plid = layout.getPlid();
255: layoutFriendlyURL = PortalUtil.getLayoutFriendlyURL(layout,
256: themeDisplay);
257: }
258:
259: String forwardURL = layoutFriendlyURL;
260:
261: if (Validator.isNull(forwardURL)) {
262: forwardURL = themeDisplay.getPathMain()
263: + "/portal/layout?p_l_id=" + plid;
264:
265: if (Validator.isNotNull(themeDisplay.getDoAsUserId())) {
266: forwardURL = Http.addParameter(forwardURL,
267: "doAsUserId", themeDisplay.getDoAsUserId());
268: }
269: }
270:
271: if (_log.isDebugEnabled()) {
272: _log.debug("Forward layout to " + forwardURL);
273: }
274:
275: req.setAttribute(WebKeys.FORWARD_URL, forwardURL);
276: }
277:
278: protected void includeLayoutContent(HttpServletRequest req,
279: HttpServletResponse res, ThemeDisplay themeDisplay,
280: Layout layout) throws Exception {
281:
282: ServletContext ctx = (ServletContext) req
283: .getAttribute(WebKeys.CTX);
284:
285: String path = StrutsUtil.TEXT_HTML_DIR;
286:
287: if (BrowserSniffer.is_wap_xhtml(req)) {
288: path = StrutsUtil.TEXT_WAP_DIR;
289: }
290:
291: // Manually check the p_p_id. See LEP-1724.
292:
293: if (themeDisplay.isStateExclusive()
294: || Validator.isNotNull(ParamUtil.getString(req,
295: "p_p_id"))) {
296:
297: path += "/portal/layout/view/portlet.jsp";
298: } else {
299: path += PortalUtil.getLayoutViewPage(layout);
300: }
301:
302: RequestDispatcher rd = ctx.getRequestDispatcher(path);
303:
304: StringServletResponse stringServletRes = new StringServletResponse(
305: res);
306:
307: rd.include(req, stringServletRes);
308:
309: req.setAttribute(WebKeys.LAYOUT_CONTENT, stringServletRes
310: .getString());
311: }
312:
313: protected Portlet processActionRequest(HttpServletRequest req,
314: HttpServletResponse res) throws Exception {
315:
316: return processPortletRequest(req, res, true);
317: }
318:
319: protected Portlet processPortletRequest(HttpServletRequest req,
320: HttpServletResponse res, boolean action) throws Exception {
321:
322: HttpSession ses = req.getSession();
323:
324: long companyId = PortalUtil.getCompanyId(req);
325: User user = PortalUtil.getUser(req);
326: Layout layout = (Layout) req.getAttribute(WebKeys.LAYOUT);
327: String portletId = ParamUtil.getString(req, "p_p_id");
328:
329: Portlet portlet = PortletLocalServiceUtil.getPortletById(
330: companyId, portletId);
331:
332: if (portlet == null) {
333: return null;
334: }
335:
336: ServletContext ctx = (ServletContext) req
337: .getAttribute(WebKeys.CTX);
338:
339: CachePortlet cachePortlet = PortletInstanceFactory.create(
340: portlet, ctx);
341:
342: if (user != null) {
343: CachePortlet.clearResponse(ses, layout.getPrimaryKey(),
344: portletId, LanguageUtil.getLanguageId(req));
345: }
346:
347: PortletPreferencesIds portletPreferencesIds = PortletPreferencesFactoryUtil
348: .getPortletPreferencesIds(req, portletId);
349:
350: PortletPreferences portletPreferences = PortletPreferencesLocalServiceUtil
351: .getPreferences(portletPreferencesIds);
352:
353: PortletConfig portletConfig = PortletConfigFactory.create(
354: portlet, ctx);
355: PortletContext portletCtx = portletConfig.getPortletContext();
356:
357: WindowState windowState = new WindowState(ParamUtil.getString(
358: req, "p_p_state"));
359:
360: PortletMode portletMode = new PortletMode(ParamUtil.getString(
361: req, "p_p_mode"));
362:
363: if (action) {
364: String contentType = req
365: .getHeader(HttpHeaders.CONTENT_TYPE);
366:
367: if (_log.isDebugEnabled()) {
368: _log.debug("Content type " + contentType);
369: }
370:
371: UploadServletRequest uploadReq = null;
372:
373: try {
374: if ((contentType != null)
375: && (contentType
376: .startsWith(ContentTypes.MULTIPART_FORM_DATA))) {
377:
378: if (!cachePortlet.getPortletConfig().isWARFile()
379: || cachePortlet.isStrutsPortlet()) {
380:
381: uploadReq = new UploadServletRequest(req);
382:
383: req = uploadReq;
384: }
385: }
386:
387: ActionRequestImpl actionRequestImpl = ActionRequestFactory
388: .create(req, portlet, cachePortlet, portletCtx,
389: windowState, portletMode,
390: portletPreferences, layout.getPlid());
391:
392: ActionResponseImpl actionResponseImpl = ActionResponseFactory
393: .create(actionRequestImpl, res, portletId,
394: user, layout, windowState, portletMode);
395:
396: actionRequestImpl.defineObjects(portletConfig,
397: actionResponseImpl);
398:
399: cachePortlet.processAction(actionRequestImpl,
400: actionResponseImpl);
401:
402: RenderParametersPool.put(req, layout.getPlid(),
403: portletId, actionResponseImpl
404: .getRenderParameters());
405: } finally {
406: if (uploadReq != null) {
407: uploadReq.cleanUp();
408: }
409: }
410: } else {
411: PortalUtil.updateWindowState(portletId, user, layout,
412: windowState, req);
413:
414: PortalUtil.updatePortletMode(portletId, user, layout,
415: portletMode, req);
416: }
417:
418: return portlet;
419: }
420:
421: protected Portlet processRenderRequest(HttpServletRequest req,
422: HttpServletResponse res) throws Exception {
423:
424: return processPortletRequest(req, res, false);
425: }
426:
427: protected void redirectActionURL(HttpServletRequest req,
428: HttpServletResponse res,
429: ActionResponseImpl actionResponseImpl, Portlet portlet)
430: throws Exception {
431:
432: ActionRequestImpl actionRequestImpl = (ActionRequestImpl) req
433: .getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
434:
435: Layout layout = (Layout) req.getAttribute(WebKeys.LAYOUT);
436:
437: PortletURL portletURL = new PortletURLImpl(actionRequestImpl,
438: actionRequestImpl.getPortletName(), layout
439: .getLayoutId(), false);
440:
441: Map renderParameters = actionResponseImpl.getRenderParameters();
442:
443: Iterator itr = renderParameters.entrySet().iterator();
444:
445: while (itr.hasNext()) {
446: Map.Entry entry = (Map.Entry) itr.next();
447:
448: String key = (String) entry.getKey();
449: Object value = entry.getValue();
450:
451: if (value instanceof String) {
452: portletURL.setParameter(key, (String) value);
453: } else if (value instanceof String[]) {
454: portletURL.setParameter(key, (String[]) value);
455: }
456: }
457:
458: res.sendRedirect(portletURL.toString());
459: }
460:
461: protected void serverExclusiveResource(HttpServletRequest req,
462: HttpServletResponse res, ThemeDisplay themeDisplay)
463: throws Exception {
464:
465: RenderRequestImpl renderRequestImpl = (RenderRequestImpl) req
466: .getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);
467:
468: RenderResponseImpl renderResponseImpl = (RenderResponseImpl) req
469: .getAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);
470:
471: StringServletResponse stringServletResponse = (StringServletResponse) renderRequestImpl
472: .getAttribute(WebKeys.STRING_SERVLET_RESPONSE);
473:
474: renderResponseImpl.transferHeaders(res);
475:
476: if (stringServletResponse.isCalledGetOutputStream()) {
477: InputStream is = new ByteArrayInputStream(
478: stringServletResponse.getByteArrayMaker()
479: .toByteArray());
480:
481: ServletResponseUtil.sendFile(res, renderResponseImpl
482: .getResourceName(), is, renderResponseImpl
483: .getContentType());
484: } else {
485: byte[] content = stringServletResponse.getString()
486: .getBytes(StringPool.UTF8);
487:
488: ServletResponseUtil.sendFile(res, renderResponseImpl
489: .getResourceName(), content, renderResponseImpl
490: .getContentType());
491: }
492:
493: RenderRequestFactory.recycle(renderRequestImpl);
494: RenderResponseFactory.recycle(renderResponseImpl);
495: }
496:
497: private static Log _log = LogFactory.getLog(LayoutAction.class);
498:
499: }
|