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