2 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
\r
4 * This library is free software; you can redistribute it and/or modify it under
\r
5 * the terms of the GNU Lesser General Public License as published by the Free
\r
6 * Software Foundation; either version 2.1 of the License, or (at your option)
\r
9 * This library is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
\r
15 package com.liferay.portal.struts;
\r
17 import com.liferay.portal.kernel.log.Log;
\r
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
\r
19 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
\r
20 import com.liferay.portal.kernel.util.CharPool;
\r
21 import com.liferay.portal.kernel.util.JavaConstants;
\r
22 import com.liferay.portal.kernel.util.StringPool;
\r
23 import com.liferay.portal.kernel.util.Validator;
\r
24 import com.liferay.portal.model.Layout;
\r
25 import com.liferay.portal.model.Portlet;
\r
26 import com.liferay.portal.security.auth.PrincipalException;
\r
27 import com.liferay.portal.security.permission.ActionKeys;
\r
28 import com.liferay.portal.security.permission.PermissionChecker;
\r
29 import com.liferay.portal.service.PortletLocalServiceUtil;
\r
30 import com.liferay.portal.service.permission.PortletPermissionUtil;
\r
31 import com.liferay.portal.theme.ThemeDisplay;
\r
32 import com.liferay.portal.util.PortalUtil;
\r
33 import com.liferay.portal.util.PropsValues;
\r
34 import com.liferay.portal.util.WebKeys;
\r
35 import com.liferay.portlet.ActionResponseImpl;
\r
36 import com.liferay.portlet.PortletConfigImpl;
\r
37 import com.liferay.portlet.PortletRequestDispatcherImpl;
\r
39 import java.io.IOException;
\r
41 import java.lang.reflect.Constructor;
\r
43 import javax.portlet.ActionRequest;
\r
44 import javax.portlet.ActionResponse;
\r
45 import javax.portlet.PortletContext;
\r
46 import javax.portlet.PortletException;
\r
47 import javax.portlet.PortletRequest;
\r
48 import javax.portlet.PortletResponse;
\r
49 import javax.portlet.RenderRequest;
\r
50 import javax.portlet.RenderResponse;
\r
51 import javax.portlet.ResourceRequest;
\r
52 import javax.portlet.ResourceResponse;
\r
54 import javax.servlet.ServletException;
\r
55 import javax.servlet.http.HttpServletRequest;
\r
56 import javax.servlet.http.HttpServletResponse;
\r
58 import org.apache.struts.Globals;
\r
59 import org.apache.struts.action.Action;
\r
60 import org.apache.struts.action.ActionErrors;
\r
61 import org.apache.struts.action.ActionForm;
\r
62 import org.apache.struts.action.ActionForward;
\r
63 import org.apache.struts.action.ActionMapping;
\r
64 import org.apache.struts.action.ActionServlet;
\r
65 import org.apache.struts.config.ActionConfig;
\r
66 import org.apache.struts.config.ForwardConfig;
\r
67 import org.apache.struts.config.ModuleConfig;
\r
68 import org.apache.struts.tiles.TilesRequestProcessor;
\r
69 import org.apache.struts.util.MessageResources;
\r
72 * @author Brian Wing Shun Chan
\r
73 * @author Raymond Augé
\r
75 public class PortletRequestProcessor extends TilesRequestProcessor {
\r
77 public static PortletRequestProcessor getInstance(
\r
78 ActionServlet servlet, ModuleConfig moduleConfig)
\r
79 throws ServletException {
\r
82 String className = PropsValues.STRUTS_PORTLET_REQUEST_PROCESSOR;
\r
84 Class<?> clazz = Class.forName(className);
\r
86 Constructor<?> constructor = clazz.getConstructor(
\r
87 ActionServlet.class, ModuleConfig.class);
\r
89 PortletRequestProcessor portletReqProcessor =
\r
90 (PortletRequestProcessor)constructor.newInstance(
\r
91 servlet, moduleConfig);
\r
93 return portletReqProcessor;
\r
95 catch (Exception e) {
\r
98 return new PortletRequestProcessor(servlet, moduleConfig);
\r
102 public PortletRequestProcessor(
\r
103 ActionServlet actionServlet, ModuleConfig moduleConfig)
\r
104 throws ServletException {
\r
106 init(actionServlet, moduleConfig);
\r
109 public void process(
\r
110 ActionRequest actionRequest, ActionResponse actionResponse,
\r
112 throws IOException, ServletException {
\r
114 ActionResponseImpl actionResponseImpl =
\r
115 (ActionResponseImpl)actionResponse;
\r
117 HttpServletRequest request = PortalUtil.getHttpServletRequest(
\r
119 HttpServletResponse response = PortalUtil.getHttpServletResponse(
\r
122 ActionMapping actionMapping = processMapping(request, response, path);
\r
124 if (actionMapping == null) {
\r
128 if (!processRoles(request, response, actionMapping, true)) {
\r
132 ActionForm actionForm = processActionForm(
\r
133 request, response, actionMapping);
\r
135 processPopulate(request, response, actionForm, actionMapping);
\r
137 if (!processValidateAction(
\r
138 request, response, actionForm, actionMapping)) {
\r
143 PortletAction portletAction = (PortletAction)processActionCreate(
\r
144 request, response, actionMapping);
\r
146 if (portletAction == null) {
\r
150 PortletConfigImpl portletConfigImpl =
\r
151 (PortletConfigImpl)actionRequest.getAttribute(
\r
152 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
155 if (portletAction.isCheckMethodOnProcessAction()) {
\r
156 if (!PortalUtil.isMethodPost(actionRequest)) {
\r
157 String currentURL = PortalUtil.getCurrentURL(actionRequest);
\r
159 if (_log.isWarnEnabled()) {
\r
161 "This URL can only be invoked using POST: " +
\r
165 throw new PrincipalException(currentURL);
\r
169 portletAction.processAction(
\r
170 actionMapping, actionForm, portletConfigImpl, actionRequest,
\r
173 catch (Exception e) {
\r
174 String exceptionId =
\r
175 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
\r
176 portletConfigImpl.getPortletId();
\r
178 actionRequest.setAttribute(exceptionId, e);
\r
181 String forward = (String)actionRequest.getAttribute(
\r
182 PortletAction.getForwardKey(actionRequest));
\r
184 if (forward != null) {
\r
185 String queryString = StringPool.BLANK;
\r
187 int pos = forward.indexOf(CharPool.QUESTION);
\r
190 queryString = forward.substring(pos + 1);
\r
191 forward = forward.substring(0, pos);
\r
194 ActionForward actionForward = actionMapping.findForward(forward);
\r
196 if ((actionForward != null) && actionForward.getRedirect()) {
\r
197 String forwardPath = actionForward.getPath();
\r
199 if (forwardPath.startsWith(StringPool.SLASH)) {
\r
200 LiferayPortletURL forwardURL =
\r
201 (LiferayPortletURL)actionResponseImpl.createRenderURL();
\r
203 forwardURL.setParameter("struts_action", forwardPath);
\r
205 StrutsURLEncoder.setParameters(forwardURL, queryString);
\r
207 forwardPath = forwardURL.toString();
\r
210 actionResponse.sendRedirect(forwardPath);
\r
215 public void process(
\r
216 RenderRequest renderRequest, RenderResponse renderResponse)
\r
217 throws IOException, ServletException {
\r
219 HttpServletRequest request = PortalUtil.getHttpServletRequest(
\r
221 HttpServletResponse response = PortalUtil.getHttpServletResponse(
\r
224 process(request, response);
\r
227 public void process(
\r
228 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
\r
229 throws IOException, ServletException {
\r
231 HttpServletRequest request = PortalUtil.getHttpServletRequest(
\r
233 HttpServletResponse response = PortalUtil.getHttpServletResponse(
\r
236 process(request, response);
\r
240 public ActionMapping processMapping(
\r
241 HttpServletRequest request, HttpServletResponse response, String path) {
\r
243 if (path == null) {
\r
247 ActionMapping actionMapping = null;
\r
249 long companyId = PortalUtil.getCompanyId(request);
\r
251 PortletConfigImpl portletConfigImpl =
\r
252 (PortletConfigImpl)request.getAttribute(
\r
253 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
256 Portlet portlet = PortletLocalServiceUtil.getPortletById(
\r
257 companyId, portletConfigImpl.getPortletId());
\r
259 if (StrutsActionRegistryUtil.getAction(path) != null) {
\r
260 actionMapping = (ActionMapping)moduleConfig.findActionConfig(
\r
263 if (actionMapping == null) {
\r
264 actionMapping = new ActionMapping();
\r
266 actionMapping.setModuleConfig(moduleConfig);
\r
267 actionMapping.setPath(path);
\r
269 request.setAttribute(Globals.MAPPING_KEY, actionMapping);
\r
272 else if (moduleConfig.findActionConfig(path) != null) {
\r
273 actionMapping = super.processMapping(request, response, path);
\r
275 else if (Validator.isNotNull(portlet.getParentStrutsPath())) {
\r
276 int pos = path.indexOf(StringPool.SLASH, 1);
\r
278 String parentPath =
\r
279 StringPool.SLASH + portlet.getParentStrutsPath() +
\r
280 path.substring(pos);
\r
282 if (StrutsActionRegistryUtil.getAction(parentPath) != null) {
\r
284 (ActionMapping)moduleConfig.findActionConfig(path);
\r
286 if (actionMapping == null) {
\r
287 actionMapping = new ActionMapping();
\r
289 actionMapping.setModuleConfig(moduleConfig);
\r
290 actionMapping.setPath(parentPath);
\r
292 request.setAttribute(
\r
293 Globals.MAPPING_KEY, actionMapping);
\r
296 else if (moduleConfig.findActionConfig(parentPath) != null) {
\r
297 actionMapping = super.processMapping(
\r
298 request, response, parentPath);
\r
302 catch (Exception e) {
\r
305 if (actionMapping == null) {
\r
306 MessageResources messageResources = getInternal();
\r
308 String msg = messageResources.getMessage("processInvalid");
\r
310 //_log.error("User ID " + request.getRemoteUser());
\r
311 //_log.error("Current URL " + PortalUtil.getCurrentURL(request));
\r
312 //_log.error("Referer " + request.getHeader("Referer"));
\r
313 //_log.error("Remote address " + request.getRemoteAddr());
\r
315 //_log.error(msg + " " + path);
\r
318 return actionMapping;
\r
322 protected void doForward(
\r
323 String uri, HttpServletRequest request,
\r
324 HttpServletResponse response)
\r
325 throws IOException, ServletException {
\r
327 doInclude(uri, request, response);
\r
331 protected void doInclude(
\r
332 String uri, HttpServletRequest request,
\r
333 HttpServletResponse response)
\r
334 throws IOException, ServletException {
\r
336 PortletConfigImpl portletConfigImpl =
\r
337 (PortletConfigImpl)request.getAttribute(
\r
338 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
340 PortletContext portletContext = portletConfigImpl.getPortletContext();
\r
342 PortletRequest portletRequest = (PortletRequest)request.getAttribute(
\r
343 JavaConstants.JAVAX_PORTLET_REQUEST);
\r
345 PortletResponse portletResponse = (PortletResponse)request.getAttribute(
\r
346 JavaConstants.JAVAX_PORTLET_RESPONSE);
\r
348 PortletRequestDispatcherImpl portletRequestDispatcher =
\r
349 (PortletRequestDispatcherImpl)portletContext.getRequestDispatcher(
\r
350 StrutsUtil.TEXT_HTML_DIR + uri);
\r
353 if (portletRequestDispatcher == null) {
\r
354 _log.error(uri + " is not a valid include");
\r
357 portletRequestDispatcher.include(
\r
358 portletRequest, portletResponse, true);
\r
361 catch (PortletException pe) {
\r
362 Throwable cause = pe.getCause();
\r
364 if (cause instanceof ServletException) {
\r
365 throw (ServletException)cause;
\r
368 _log.error(cause, cause);
\r
374 protected Action processActionCreate(
\r
375 HttpServletRequest request, HttpServletResponse response,
\r
376 ActionMapping actionMapping)
\r
377 throws IOException {
\r
379 PortletActionAdapter portletActionAdapter =
\r
380 (PortletActionAdapter)StrutsActionRegistryUtil.getAction(
\r
381 actionMapping.getPath());
\r
383 if (portletActionAdapter != null) {
\r
384 ActionConfig actionConfig = moduleConfig.findActionConfig(
\r
385 actionMapping.getPath());
\r
387 if (actionConfig != null) {
\r
388 PortletAction originalPortletAction =
\r
389 (PortletAction)super.processActionCreate(
\r
390 request, response, actionMapping);
\r
392 portletActionAdapter.setOriginalPortletAction(
\r
393 originalPortletAction);
\r
396 return portletActionAdapter;
\r
399 return super.processActionCreate(request, response, actionMapping);
\r
403 protected ActionForm processActionForm(
\r
404 HttpServletRequest request, HttpServletResponse response,
\r
405 ActionMapping actionMapping) {
\r
407 ActionForm actionForm = super.processActionForm(
\r
408 request, response, actionMapping);
\r
410 if (actionForm instanceof InitializableActionForm) {
\r
411 InitializableActionForm initializableActionForm =
\r
412 (InitializableActionForm)actionForm;
\r
414 initializableActionForm.init(request, response, actionMapping);
\r
421 protected ActionForward processActionPerform(
\r
422 HttpServletRequest request, HttpServletResponse response,
\r
423 Action action, ActionForm actionForm, ActionMapping actionMapping)
\r
424 throws IOException, ServletException {
\r
426 PortletConfigImpl portletConfigImpl =
\r
427 (PortletConfigImpl)request.getAttribute(
\r
428 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
430 String exceptionId =
\r
431 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
\r
432 portletConfigImpl.getPortletId();
\r
434 Exception e = (Exception)request.getAttribute(exceptionId);
\r
437 return processException(
\r
438 request, response, e, actionForm, actionMapping);
\r
441 return super.processActionPerform(
\r
442 request, response, action, actionForm, actionMapping);
\r
447 protected void processForwardConfig(
\r
448 HttpServletRequest request, HttpServletResponse response,
\r
449 ForwardConfig forward)
\r
450 throws IOException, ServletException {
\r
452 if (forward == null) {
\r
453 _log.error("Forward does not exist");
\r
457 // Don't render a null path. This is useful if you're sending a file
\r
458 // in an exclusive window state.
\r
460 if (forward.getPath().equals(ActionConstants.COMMON_NULL)) {
\r
465 super.processForwardConfig(request, response, forward);
\r
469 protected HttpServletRequest processMultipart(HttpServletRequest request) {
\r
471 // Disable Struts from automatically wrapping a multipart request
\r
477 protected String processPath(
\r
478 HttpServletRequest request, HttpServletResponse response) {
\r
480 String path = request.getParameter("struts_action");
\r
482 if (_log.isDebugEnabled()) {
\r
483 _log.debug("Getting request parameter path " + path);
\r
486 if (Validator.isNull(path)) {
\r
487 if (_log.isDebugEnabled()) {
\r
488 _log.debug("Getting request attribute path " + path);
\r
491 path = (String)request.getAttribute(WebKeys.PORTLET_STRUTS_ACTION);
\r
494 if (path == null) {
\r
495 PortletConfigImpl portletConfigImpl =
\r
496 (PortletConfigImpl)request.getAttribute(
\r
497 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
500 portletConfigImpl.getPortletName() +
\r
501 " does not have any paths specified");
\r
504 if (_log.isDebugEnabled()) {
\r
505 _log.debug("Processing path " + path);
\r
513 protected boolean processRoles(
\r
514 HttpServletRequest request, HttpServletResponse response,
\r
515 ActionMapping actionMapping)
\r
516 throws IOException, ServletException {
\r
518 return processRoles(request, response, actionMapping, false);
\r
521 protected boolean processRoles(
\r
522 HttpServletRequest request, HttpServletResponse response,
\r
523 ActionMapping actionMapping, boolean action)
\r
524 throws IOException, ServletException {
\r
526 long companyId = PortalUtil.getCompanyId(request);
\r
528 String path = actionMapping.getPath();
\r
531 PortletConfigImpl portletConfigImpl =
\r
532 (PortletConfigImpl)request.getAttribute(
\r
533 JavaConstants.JAVAX_PORTLET_CONFIG);
\r
535 Portlet portlet = PortletLocalServiceUtil.getPortletById(
\r
536 companyId, portletConfigImpl.getPortletId());
\r
538 if (portlet == null) {
\r
542 String strutsPath = path.substring(
\r
543 1, path.lastIndexOf(CharPool.SLASH));
\r
545 if (!strutsPath.equals(portlet.getStrutsPath()) &&
\r
546 !strutsPath.equals(portlet.getParentStrutsPath())) {
\r
547 if (_log.isWarnEnabled()) {
\r
549 "The struts path " + strutsPath + " does not belong " +
\r
550 "to portlet " + portlet.getPortletId() + ". " +
\r
551 "Check the definition in liferay-portlet.xml");
\r
554 throw new PrincipalException();
\r
556 else if (portlet.isActive()) {
\r
557 if (PortalUtil.isAllowAddPortletDefaultResource(
\r
558 request, portlet)) {
\r
560 PortalUtil.addPortletDefaultResource(request, portlet);
\r
563 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
\r
564 WebKeys.THEME_DISPLAY);
\r
566 Layout layout = themeDisplay.getLayout();
\r
567 PermissionChecker permissionChecker =
\r
568 themeDisplay.getPermissionChecker();
\r
570 if (!PortletPermissionUtil.contains(
\r
571 permissionChecker, layout, portlet, ActionKeys.VIEW)) {
\r
573 throw new PrincipalException();
\r
576 else if (!portlet.isActive()) {
\r
577 ForwardConfig forwardConfig = actionMapping.findForward(
\r
578 _PATH_PORTAL_PORTLET_INACTIVE);
\r
581 processForwardConfig(request, response, forwardConfig);
\r
587 catch (Exception e) {
\r
588 if (_log.isWarnEnabled()) {
\r
589 _log.warn(e.getMessage());
\r
592 ForwardConfig forwardConfig = actionMapping.findForward(
\r
593 _PATH_PORTAL_PORTLET_ACCESS_DENIED);
\r
596 processForwardConfig(request, response, forwardConfig);
\r
605 protected boolean processValidateAction(
\r
606 HttpServletRequest request, HttpServletResponse response,
\r
607 ActionForm actionForm, ActionMapping actionMapping) {
\r
609 if (actionForm == null) {
\r
613 if (request.getAttribute(Globals.CANCEL_KEY) != null) {
\r
617 if (!actionMapping.getValidate()) {
\r
621 ActionErrors errors = actionForm.validate(actionMapping, request);
\r
623 if ((errors == null) || errors.isEmpty()) {
\r
627 if (actionForm.getMultipartRequestHandler() != null) {
\r
628 actionForm.getMultipartRequestHandler().rollback();
\r
631 String input = actionMapping.getInput();
\r
633 if (input == null) {
\r
634 _log.error("Validation failed but no input form is available");
\r
639 request.setAttribute(Globals.ERROR_KEY, errors);
\r
641 // Struts normally calls internalModuleRelativeForward which breaks
\r
642 // if called inside processAction
\r
644 request.setAttribute(PortletAction.getForwardKey(request), input);
\r
649 private static final String _PATH_PORTAL_PORTLET_ACCESS_DENIED =
\r
650 "/portal/portlet_access_denied";
\r
652 private static final String _PATH_PORTAL_PORTLET_INACTIVE =
\r
653 "/portal/portlet_inactive";
\r
655 private static Log _log = LogFactoryUtil.getLog(
\r
656 PortletRequestProcessor.class);
\r