001
014
015 package com.liferay.portal.struts;
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.util.CharPool;
021 import com.liferay.portal.kernel.util.JavaConstants;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.Validator;
024 import com.liferay.portal.model.Layout;
025 import com.liferay.portal.model.Portlet;
026 import com.liferay.portal.security.auth.PrincipalException;
027 import com.liferay.portal.security.permission.ActionKeys;
028 import com.liferay.portal.security.permission.PermissionChecker;
029 import com.liferay.portal.service.PortletLocalServiceUtil;
030 import com.liferay.portal.service.permission.PortletPermissionUtil;
031 import com.liferay.portal.theme.ThemeDisplay;
032 import com.liferay.portal.util.PortalUtil;
033 import com.liferay.portal.util.PropsValues;
034 import com.liferay.portal.util.WebKeys;
035 import com.liferay.portlet.ActionResponseImpl;
036 import com.liferay.portlet.PortletConfigImpl;
037 import com.liferay.portlet.PortletRequestDispatcherImpl;
038
039 import java.io.IOException;
040
041 import java.lang.reflect.Constructor;
042
043 import javax.portlet.ActionRequest;
044 import javax.portlet.ActionResponse;
045 import javax.portlet.EventRequest;
046 import javax.portlet.EventResponse;
047 import javax.portlet.PortletContext;
048 import javax.portlet.PortletException;
049 import javax.portlet.PortletRequest;
050 import javax.portlet.PortletResponse;
051 import javax.portlet.RenderRequest;
052 import javax.portlet.RenderResponse;
053 import javax.portlet.ResourceRequest;
054 import javax.portlet.ResourceResponse;
055
056 import javax.servlet.ServletException;
057 import javax.servlet.http.HttpServletRequest;
058 import javax.servlet.http.HttpServletResponse;
059
060 import org.apache.struts.Globals;
061 import org.apache.struts.action.Action;
062 import org.apache.struts.action.ActionErrors;
063 import org.apache.struts.action.ActionForm;
064 import org.apache.struts.action.ActionForward;
065 import org.apache.struts.action.ActionMapping;
066 import org.apache.struts.action.ActionServlet;
067 import org.apache.struts.config.ActionConfig;
068 import org.apache.struts.config.ForwardConfig;
069 import org.apache.struts.config.ModuleConfig;
070 import org.apache.struts.tiles.TilesRequestProcessor;
071 import org.apache.struts.util.MessageResources;
072
073
077 public class PortletRequestProcessor extends TilesRequestProcessor {
078
079 public static PortletRequestProcessor getInstance(
080 ActionServlet servlet, ModuleConfig moduleConfig)
081 throws ServletException {
082
083 try {
084 String className = PropsValues.STRUTS_PORTLET_REQUEST_PROCESSOR;
085
086 Class<?> clazz = Class.forName(className);
087
088 Constructor<?> constructor = clazz.getConstructor(
089 ActionServlet.class, ModuleConfig.class);
090
091 PortletRequestProcessor portletReqProcessor =
092 (PortletRequestProcessor)constructor.newInstance(
093 servlet, moduleConfig);
094
095 return portletReqProcessor;
096 }
097 catch (Exception e) {
098 _log.error(e);
099
100 return new PortletRequestProcessor(servlet, moduleConfig);
101 }
102 }
103
104 public PortletRequestProcessor(
105 ActionServlet actionServlet, ModuleConfig moduleConfig)
106 throws ServletException {
107
108 init(actionServlet, moduleConfig);
109 }
110
111 public void process(
112 ActionRequest actionRequest, ActionResponse actionResponse,
113 String path)
114 throws IOException, ServletException {
115
116 ActionResponseImpl actionResponseImpl =
117 (ActionResponseImpl)actionResponse;
118
119 HttpServletRequest request = PortalUtil.getHttpServletRequest(
120 actionRequest);
121 HttpServletResponse response = PortalUtil.getHttpServletResponse(
122 actionResponse);
123
124 ActionMapping actionMapping = processMapping(request, response, path);
125
126 if (actionMapping == null) {
127 return;
128 }
129
130 if (!processRoles(request, response, actionMapping, true)) {
131 return;
132 }
133
134 ActionForm actionForm = processActionForm(
135 request, response, actionMapping);
136
137 processPopulate(request, response, actionForm, actionMapping);
138
139 if (!processValidateAction(
140 request, response, actionForm, actionMapping)) {
141
142 return;
143 }
144
145 PortletAction portletAction = (PortletAction)processActionCreate(
146 request, response, actionMapping);
147
148 if (portletAction == null) {
149 return;
150 }
151
152 PortletConfigImpl portletConfigImpl =
153 (PortletConfigImpl)actionRequest.getAttribute(
154 JavaConstants.JAVAX_PORTLET_CONFIG);
155
156 try {
157 if (portletAction.isCheckMethodOnProcessAction()) {
158 if (!PortalUtil.isMethodPost(actionRequest)) {
159 String currentURL = PortalUtil.getCurrentURL(actionRequest);
160
161 if (_log.isWarnEnabled()) {
162 _log.warn(
163 "This URL can only be invoked using POST: " +
164 currentURL);
165 }
166
167 throw new PrincipalException(currentURL);
168 }
169 }
170
171 portletAction.processAction(
172 actionMapping, actionForm, portletConfigImpl, actionRequest,
173 actionResponse);
174 }
175 catch (Exception e) {
176 String exceptionId =
177 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
178 portletConfigImpl.getPortletId();
179
180 actionRequest.setAttribute(exceptionId, e);
181 }
182
183 String forward = (String)actionRequest.getAttribute(
184 PortletAction.getForwardKey(actionRequest));
185
186 if (forward != null) {
187 String queryString = StringPool.BLANK;
188
189 int pos = forward.indexOf(CharPool.QUESTION);
190
191 if (pos != -1) {
192 queryString = forward.substring(pos + 1);
193 forward = forward.substring(0, pos);
194 }
195
196 ActionForward actionForward = actionMapping.findForward(forward);
197
198 if ((actionForward != null) && actionForward.getRedirect()) {
199 String forwardPath = actionForward.getPath();
200
201 if (forwardPath.startsWith(StringPool.SLASH)) {
202 LiferayPortletURL forwardURL =
203 (LiferayPortletURL)actionResponseImpl.createRenderURL();
204
205 forwardURL.setParameter("struts_action", forwardPath);
206
207 StrutsURLEncoder.setParameters(forwardURL, queryString);
208
209 forwardPath = forwardURL.toString();
210 }
211
212 actionResponse.sendRedirect(forwardPath);
213 }
214 }
215 }
216
217 public void process(EventRequest eventRequest, EventResponse eventResponse)
218 throws IOException, ServletException {
219
220 HttpServletRequest request = PortalUtil.getHttpServletRequest(
221 eventRequest);
222 HttpServletResponse response = PortalUtil.getHttpServletResponse(
223 eventResponse);
224
225 process(request, response);
226 }
227
228 public void process(
229 RenderRequest renderRequest, RenderResponse renderResponse)
230 throws IOException, ServletException {
231
232 HttpServletRequest request = PortalUtil.getHttpServletRequest(
233 renderRequest);
234 HttpServletResponse response = PortalUtil.getHttpServletResponse(
235 renderResponse);
236
237 process(request, response);
238 }
239
240 public void process(
241 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
242 throws IOException, ServletException {
243
244 HttpServletRequest request = PortalUtil.getHttpServletRequest(
245 resourceRequest);
246 HttpServletResponse response = PortalUtil.getHttpServletResponse(
247 resourceResponse);
248
249 process(request, response);
250 }
251
252 @Override
253 public ActionMapping processMapping(
254 HttpServletRequest request, HttpServletResponse response, String path) {
255
256 if (path == null) {
257 return null;
258 }
259
260 ActionMapping actionMapping = null;
261
262 long companyId = PortalUtil.getCompanyId(request);
263
264 PortletConfigImpl portletConfigImpl =
265 (PortletConfigImpl)request.getAttribute(
266 JavaConstants.JAVAX_PORTLET_CONFIG);
267
268 try {
269 Portlet portlet = PortletLocalServiceUtil.getPortletById(
270 companyId, portletConfigImpl.getPortletId());
271
272 if (StrutsActionRegistryUtil.getAction(path) != null) {
273 actionMapping = (ActionMapping)moduleConfig.findActionConfig(
274 path);
275
276 if (actionMapping == null) {
277 actionMapping = new ActionMapping();
278
279 actionMapping.setModuleConfig(moduleConfig);
280 actionMapping.setPath(path);
281
282 request.setAttribute(Globals.MAPPING_KEY, actionMapping);
283 }
284 }
285 else if (moduleConfig.findActionConfig(path) != null) {
286 actionMapping = super.processMapping(request, response, path);
287 }
288 else if (Validator.isNotNull(portlet.getParentStrutsPath())) {
289 int pos = path.indexOf(StringPool.SLASH, 1);
290
291 String parentPath =
292 StringPool.SLASH + portlet.getParentStrutsPath() +
293 path.substring(pos);
294
295 if (StrutsActionRegistryUtil.getAction(parentPath) != null) {
296 actionMapping =
297 (ActionMapping)moduleConfig.findActionConfig(
298 parentPath);
299
300 if (actionMapping == null) {
301 actionMapping = new ActionMapping();
302
303 actionMapping.setModuleConfig(moduleConfig);
304 actionMapping.setPath(parentPath);
305
306 request.setAttribute(
307 Globals.MAPPING_KEY, actionMapping);
308 }
309 }
310 else if (moduleConfig.findActionConfig(parentPath) != null) {
311 actionMapping = super.processMapping(
312 request, response, parentPath);
313 }
314 }
315 }
316 catch (Exception e) {
317 }
318
319 if (actionMapping == null) {
320 MessageResources messageResources = getInternal();
321
322 String msg = messageResources.getMessage("processInvalid");
323
324 _log.error("User ID " + request.getRemoteUser());
325 _log.error("Current URL " + PortalUtil.getCurrentURL(request));
326 _log.error("Referer " + request.getHeader("Referer"));
327 _log.error("Remote address " + request.getRemoteAddr());
328
329 _log.error(msg + " " + path);
330 }
331
332 return actionMapping;
333 }
334
335 @Override
336 protected void doForward(
337 String uri, HttpServletRequest request,
338 HttpServletResponse response)
339 throws IOException, ServletException {
340
341 doInclude(uri, request, response);
342 }
343
344 @Override
345 protected void doInclude(
346 String uri, HttpServletRequest request,
347 HttpServletResponse response)
348 throws IOException, ServletException {
349
350 PortletConfigImpl portletConfigImpl =
351 (PortletConfigImpl)request.getAttribute(
352 JavaConstants.JAVAX_PORTLET_CONFIG);
353
354 PortletContext portletContext = portletConfigImpl.getPortletContext();
355
356 PortletRequest portletRequest = (PortletRequest)request.getAttribute(
357 JavaConstants.JAVAX_PORTLET_REQUEST);
358
359 PortletResponse portletResponse = (PortletResponse)request.getAttribute(
360 JavaConstants.JAVAX_PORTLET_RESPONSE);
361
362 PortletRequestDispatcherImpl portletRequestDispatcher =
363 (PortletRequestDispatcherImpl)portletContext.getRequestDispatcher(
364 StrutsUtil.TEXT_HTML_DIR + uri);
365
366 try {
367 if (portletRequestDispatcher == null) {
368 _log.error(uri + " is not a valid include");
369 }
370 else {
371 portletRequestDispatcher.include(
372 portletRequest, portletResponse, true);
373 }
374 }
375 catch (PortletException pe) {
376 Throwable cause = pe.getCause();
377
378 if (cause instanceof ServletException) {
379 throw (ServletException)cause;
380 }
381 else {
382 _log.error(cause, cause);
383 }
384 }
385 }
386
387 @Override
388 protected Action processActionCreate(
389 HttpServletRequest request, HttpServletResponse response,
390 ActionMapping actionMapping)
391 throws IOException {
392
393 PortletActionAdapter portletActionAdapter =
394 (PortletActionAdapter)StrutsActionRegistryUtil.getAction(
395 actionMapping.getPath());
396
397 if (portletActionAdapter != null) {
398 ActionConfig actionConfig = moduleConfig.findActionConfig(
399 actionMapping.getPath());
400
401 if (actionConfig != null) {
402 PortletAction originalPortletAction =
403 (PortletAction)super.processActionCreate(
404 request, response, actionMapping);
405
406 portletActionAdapter.setOriginalPortletAction(
407 originalPortletAction);
408 }
409
410 return portletActionAdapter;
411 }
412
413 return super.processActionCreate(request, response, actionMapping);
414 }
415
416 @Override
417 protected ActionForm processActionForm(
418 HttpServletRequest request, HttpServletResponse response,
419 ActionMapping actionMapping) {
420
421 ActionForm actionForm = super.processActionForm(
422 request, response, actionMapping);
423
424 if (actionForm instanceof InitializableActionForm) {
425 InitializableActionForm initializableActionForm =
426 (InitializableActionForm)actionForm;
427
428 initializableActionForm.init(request, response, actionMapping);
429 }
430
431 return actionForm;
432 }
433
434 @Override
435 protected ActionForward processActionPerform(
436 HttpServletRequest request, HttpServletResponse response,
437 Action action, ActionForm actionForm, ActionMapping actionMapping)
438 throws IOException, ServletException {
439
440 PortletConfigImpl portletConfigImpl =
441 (PortletConfigImpl)request.getAttribute(
442 JavaConstants.JAVAX_PORTLET_CONFIG);
443
444 String exceptionId =
445 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
446 portletConfigImpl.getPortletId();
447
448 Exception e = (Exception)request.getAttribute(exceptionId);
449
450 if (e != null) {
451 return processException(
452 request, response, e, actionForm, actionMapping);
453 }
454 else {
455 return super.processActionPerform(
456 request, response, action, actionForm, actionMapping);
457 }
458 }
459
460 @Override
461 protected void processForwardConfig(
462 HttpServletRequest request, HttpServletResponse response,
463 ForwardConfig forward)
464 throws IOException, ServletException {
465
466 if (forward == null) {
467 _log.error("Forward does not exist");
468 }
469 else {
470
471
472
473
474 if (forward.getPath().equals(ActionConstants.COMMON_NULL)) {
475 return;
476 }
477 }
478
479 super.processForwardConfig(request, response, forward);
480 }
481
482 @Override
483 protected HttpServletRequest processMultipart(HttpServletRequest request) {
484
485
486
487 return request;
488 }
489
490 @Override
491 protected String processPath(
492 HttpServletRequest request, HttpServletResponse response) {
493
494 String path = request.getParameter("struts_action");
495
496 if (_log.isDebugEnabled()) {
497 _log.debug("Getting request parameter path " + path);
498 }
499
500 if (Validator.isNull(path)) {
501 if (_log.isDebugEnabled()) {
502 _log.debug("Getting request attribute path " + path);
503 }
504
505 path = (String)request.getAttribute(WebKeys.PORTLET_STRUTS_ACTION);
506 }
507
508 if (path == null) {
509 PortletConfigImpl portletConfigImpl =
510 (PortletConfigImpl)request.getAttribute(
511 JavaConstants.JAVAX_PORTLET_CONFIG);
512
513 _log.error(
514 portletConfigImpl.getPortletName() +
515 " does not have any paths specified");
516 }
517 else {
518 if (_log.isDebugEnabled()) {
519 _log.debug("Processing path " + path);
520 }
521
522 request.removeAttribute(WebKeys.PORTLET_STRUTS_ACTION);
523 }
524
525 return path;
526 }
527
528 @Override
529 protected boolean processRoles(
530 HttpServletRequest request, HttpServletResponse response,
531 ActionMapping actionMapping)
532 throws IOException, ServletException {
533
534 return processRoles(request, response, actionMapping, false);
535 }
536
537 protected boolean processRoles(
538 HttpServletRequest request, HttpServletResponse response,
539 ActionMapping actionMapping, boolean action)
540 throws IOException, ServletException {
541
542 long companyId = PortalUtil.getCompanyId(request);
543
544 String path = actionMapping.getPath();
545
546 try {
547 PortletConfigImpl portletConfigImpl =
548 (PortletConfigImpl)request.getAttribute(
549 JavaConstants.JAVAX_PORTLET_CONFIG);
550
551 Portlet portlet = PortletLocalServiceUtil.getPortletById(
552 companyId, portletConfigImpl.getPortletId());
553
554 if (portlet == null) {
555 return false;
556 }
557
558 String strutsPath = path.substring(
559 1, path.lastIndexOf(CharPool.SLASH));
560
561 if (!strutsPath.equals(portlet.getStrutsPath()) &&
562 !strutsPath.equals(portlet.getParentStrutsPath())) {
563
564 if (_log.isWarnEnabled()) {
565 _log.warn(
566 "The struts path " + strutsPath + " does not belong " +
567 "to portlet " + portlet.getPortletId() + ". " +
568 "Check the definition in liferay-portlet.xml");
569 }
570
571 throw new PrincipalException();
572 }
573 else if (portlet.isActive()) {
574 if (PortalUtil.isAllowAddPortletDefaultResource(
575 request, portlet)) {
576
577 PortalUtil.addPortletDefaultResource(request, portlet);
578 }
579
580 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
581 WebKeys.THEME_DISPLAY);
582
583 Layout layout = themeDisplay.getLayout();
584 PermissionChecker permissionChecker =
585 themeDisplay.getPermissionChecker();
586
587 if (!PortletPermissionUtil.contains(
588 permissionChecker, layout, portlet, ActionKeys.VIEW)) {
589
590 throw new PrincipalException();
591 }
592 }
593 else if (!portlet.isActive()) {
594 ForwardConfig forwardConfig = actionMapping.findForward(
595 _PATH_PORTAL_PORTLET_INACTIVE);
596
597 if (!action) {
598 processForwardConfig(request, response, forwardConfig);
599 }
600
601 return false;
602 }
603 }
604 catch (Exception e) {
605 if (_log.isWarnEnabled()) {
606 _log.warn(e.getMessage());
607 }
608
609 ForwardConfig forwardConfig = actionMapping.findForward(
610 _PATH_PORTAL_PORTLET_ACCESS_DENIED);
611
612 if (!action) {
613 processForwardConfig(request, response, forwardConfig);
614 }
615
616 return false;
617 }
618
619 return true;
620 }
621
622 protected boolean processValidateAction(
623 HttpServletRequest request, HttpServletResponse response,
624 ActionForm actionForm, ActionMapping actionMapping) {
625
626 if (actionForm == null) {
627 return true;
628 }
629
630 if (request.getAttribute(Globals.CANCEL_KEY) != null) {
631 return true;
632 }
633
634 if (!actionMapping.getValidate()) {
635 return true;
636 }
637
638 ActionErrors errors = actionForm.validate(actionMapping, request);
639
640 if ((errors == null) || errors.isEmpty()) {
641 return true;
642 }
643
644 if (actionForm.getMultipartRequestHandler() != null) {
645 actionForm.getMultipartRequestHandler().rollback();
646 }
647
648 String input = actionMapping.getInput();
649
650 if (input == null) {
651 _log.error("Validation failed but no input form is available");
652
653 return false;
654 }
655
656 request.setAttribute(Globals.ERROR_KEY, errors);
657
658
659
660
661 request.setAttribute(PortletAction.getForwardKey(request), input);
662
663 return false;
664 }
665
666 private static final String _PATH_PORTAL_PORTLET_ACCESS_DENIED =
667 "/portal/portlet_access_denied";
668
669 private static final String _PATH_PORTAL_PORTLET_INACTIVE =
670 "/portal/portlet_inactive";
671
672 private static Log _log = LogFactoryUtil.getLog(
673 PortletRequestProcessor.class);
674
675 }