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 protected void doForward(
247 String uri, HttpServletRequest request,
248 HttpServletResponse response)
249 throws IOException, ServletException {
250
251 doInclude(uri, request, response);
252 }
253
254 @Override
255 protected void doInclude(
256 String uri, HttpServletRequest request,
257 HttpServletResponse response)
258 throws IOException, ServletException {
259
260 PortletConfigImpl portletConfigImpl =
261 (PortletConfigImpl)request.getAttribute(
262 JavaConstants.JAVAX_PORTLET_CONFIG);
263
264 PortletContext portletContext = portletConfigImpl.getPortletContext();
265
266 PortletRequest portletRequest = (PortletRequest)request.getAttribute(
267 JavaConstants.JAVAX_PORTLET_REQUEST);
268
269 PortletResponse portletResponse = (PortletResponse)request.getAttribute(
270 JavaConstants.JAVAX_PORTLET_RESPONSE);
271
272 PortletRequestDispatcherImpl portletRequestDispatcher =
273 (PortletRequestDispatcherImpl)portletContext.getRequestDispatcher(
274 StrutsUtil.TEXT_HTML_DIR + uri);
275
276 try {
277 if (portletRequestDispatcher == null) {
278 _log.error(uri + " is not a valid include");
279 }
280 else {
281 portletRequestDispatcher.include(
282 portletRequest, portletResponse, true);
283 }
284 }
285 catch (PortletException pe) {
286 Throwable cause = pe.getCause();
287
288 if (cause instanceof ServletException) {
289 throw (ServletException)cause;
290 }
291 else {
292 _log.error(cause, cause);
293 }
294 }
295 }
296
297 @Override
298 protected Action processActionCreate(
299 HttpServletRequest request, HttpServletResponse response,
300 ActionMapping actionMapping)
301 throws IOException {
302
303 PortletActionAdapter portletActionAdapter =
304 (PortletActionAdapter)StrutsActionRegistryUtil.getAction(
305 actionMapping.getPath());
306
307 if (portletActionAdapter != null) {
308 ActionConfig actionConfig = moduleConfig.findActionConfig(
309 actionMapping.getPath());
310
311 if (actionConfig != null) {
312 PortletAction originalPortletAction =
313 (PortletAction)super.processActionCreate(
314 request, response, actionMapping);
315
316 portletActionAdapter.setOriginalPortletAction(
317 originalPortletAction);
318 }
319
320 return portletActionAdapter;
321 }
322
323 return super.processActionCreate(request, response, actionMapping);
324 }
325
326 @Override
327 protected ActionForm processActionForm(
328 HttpServletRequest request, HttpServletResponse response,
329 ActionMapping actionMapping) {
330
331 ActionForm actionForm = super.processActionForm(
332 request, response, actionMapping);
333
334 if (actionForm instanceof InitializableActionForm) {
335 InitializableActionForm initializableActionForm =
336 (InitializableActionForm)actionForm;
337
338 initializableActionForm.init(request, response, actionMapping);
339 }
340
341 return actionForm;
342 }
343
344 @Override
345 protected ActionForward processActionPerform(
346 HttpServletRequest request, HttpServletResponse response,
347 Action action, ActionForm actionForm, ActionMapping actionMapping)
348 throws IOException, ServletException {
349
350 PortletConfigImpl portletConfigImpl =
351 (PortletConfigImpl)request.getAttribute(
352 JavaConstants.JAVAX_PORTLET_CONFIG);
353
354 String exceptionId =
355 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
356 portletConfigImpl.getPortletId();
357
358 Exception e = (Exception)request.getAttribute(exceptionId);
359
360 if (e != null) {
361 return processException(
362 request, response, e, actionForm, actionMapping);
363 }
364 else {
365 return super.processActionPerform(
366 request, response, action, actionForm, actionMapping);
367 }
368 }
369
370 @Override
371 protected void processForwardConfig(
372 HttpServletRequest request, HttpServletResponse response,
373 ForwardConfig forward)
374 throws IOException, ServletException {
375
376 if (forward == null) {
377 _log.error("Forward does not exist");
378 }
379 else {
380
381
382
383
384 if (forward.getPath().equals(ActionConstants.COMMON_NULL)) {
385 return;
386 }
387 }
388
389 super.processForwardConfig(request, response, forward);
390 }
391
392 @Override
393 public ActionMapping processMapping(
394 HttpServletRequest request, HttpServletResponse response, String path) {
395
396 if (path == null) {
397 return null;
398 }
399
400 ActionMapping actionMapping = null;
401
402 long companyId = PortalUtil.getCompanyId(request);
403
404 PortletConfigImpl portletConfigImpl =
405 (PortletConfigImpl)request.getAttribute(
406 JavaConstants.JAVAX_PORTLET_CONFIG);
407
408 try {
409 Portlet portlet = PortletLocalServiceUtil.getPortletById(
410 companyId, portletConfigImpl.getPortletId());
411
412 if (StrutsActionRegistryUtil.getAction(path) != null) {
413 actionMapping = (ActionMapping)moduleConfig.findActionConfig(
414 path);
415
416 if (actionMapping == null) {
417 actionMapping = new ActionMapping();
418
419 actionMapping.setModuleConfig(moduleConfig);
420 actionMapping.setPath(path);
421
422 request.setAttribute(Globals.MAPPING_KEY, actionMapping);
423 }
424 }
425 else if (moduleConfig.findActionConfig(path) != null) {
426 actionMapping = super.processMapping(request, response, path);
427 }
428 else if (Validator.isNotNull(portlet.getParentStrutsPath())) {
429 int pos = path.indexOf(StringPool.SLASH, 1);
430
431 String parentPath =
432 StringPool.SLASH + portlet.getParentStrutsPath() +
433 path.substring(pos, path.length());
434
435 if (StrutsActionRegistryUtil.getAction(parentPath) != null) {
436 actionMapping =
437 (ActionMapping)moduleConfig.findActionConfig(path);
438
439 if (actionMapping == null) {
440 actionMapping = new ActionMapping();
441
442 actionMapping.setModuleConfig(moduleConfig);
443 actionMapping.setPath(parentPath);
444
445 request.setAttribute(
446 Globals.MAPPING_KEY, actionMapping);
447 }
448 }
449 else if (moduleConfig.findActionConfig(parentPath) != null) {
450 actionMapping = super.processMapping(
451 request, response, parentPath);
452 }
453 }
454 }
455 catch (Exception e) {
456 }
457
458 if (actionMapping == null) {
459 MessageResources messageResources = getInternal();
460
461 String msg = messageResources.getMessage("processInvalid");
462
463 _log.error("User ID " + request.getRemoteUser());
464 _log.error("Current URL " + PortalUtil.getCurrentURL(request));
465 _log.error("Referer " + request.getHeader("Referer"));
466 _log.error("Remote address " + request.getRemoteAddr());
467
468 _log.error(msg + " " + path);
469 }
470
471 return actionMapping;
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 =
584 actionMapping.findForward(_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 =
599 actionMapping.findForward(_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 }