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.LiferayPortletConfig;
020 import com.liferay.portal.kernel.portlet.LiferayPortletRequestDispatcher;
021 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
022 import com.liferay.portal.kernel.util.CharPool;
023 import com.liferay.portal.kernel.util.JavaConstants;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.Validator;
026 import com.liferay.portal.model.Layout;
027 import com.liferay.portal.model.Portlet;
028 import com.liferay.portal.security.auth.PrincipalException;
029 import com.liferay.portal.security.permission.ActionKeys;
030 import com.liferay.portal.security.permission.PermissionChecker;
031 import com.liferay.portal.service.PortletLocalServiceUtil;
032 import com.liferay.portal.service.permission.PortletPermissionUtil;
033 import com.liferay.portal.theme.ThemeDisplay;
034 import com.liferay.portal.util.PortalUtil;
035 import com.liferay.portal.util.PropsValues;
036 import com.liferay.portal.util.WebKeys;
037 import com.liferay.portlet.ActionResponseImpl;
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 ActionServlet.class, ModuleConfig.class);
088
089 PortletRequestProcessor portletReqProcessor =
090 (PortletRequestProcessor)constructor.newInstance(
091 servlet, moduleConfig);
092
093 return portletReqProcessor;
094 }
095 catch (Exception e) {
096 _log.error(e);
097
098 return new PortletRequestProcessor(servlet, moduleConfig);
099 }
100 }
101
102 public PortletRequestProcessor(
103 ActionServlet actionServlet, ModuleConfig moduleConfig)
104 throws ServletException {
105
106 init(actionServlet, moduleConfig);
107 }
108
109 public void process(
110 ActionRequest actionRequest, ActionResponse actionResponse,
111 String path)
112 throws IOException, ServletException {
113
114 ActionResponseImpl actionResponseImpl =
115 (ActionResponseImpl)actionResponse;
116
117 HttpServletRequest request = PortalUtil.getHttpServletRequest(
118 actionRequest);
119 HttpServletResponse response = PortalUtil.getHttpServletResponse(
120 actionResponse);
121
122 ActionMapping actionMapping = processMapping(request, response, path);
123
124 if (actionMapping == null) {
125 return;
126 }
127
128 if (!processRoles(request, response, actionMapping, true)) {
129 return;
130 }
131
132 ActionForm actionForm = processActionForm(
133 request, response, actionMapping);
134
135 processPopulate(request, response, actionForm, actionMapping);
136
137 if (!processValidateAction(
138 request, response, actionForm, actionMapping)) {
139
140 return;
141 }
142
143 PortletAction portletAction = (PortletAction)processActionCreate(
144 request, response, actionMapping);
145
146 if (portletAction == null) {
147 return;
148 }
149
150 LiferayPortletConfig liferayPortletConfig =
151 (LiferayPortletConfig)actionRequest.getAttribute(
152 JavaConstants.JAVAX_PORTLET_CONFIG);
153
154 try {
155 if (portletAction.isCheckMethodOnProcessAction()) {
156 if (!PortalUtil.isMethodPost(actionRequest)) {
157 String currentURL = PortalUtil.getCurrentURL(actionRequest);
158
159 if (_log.isWarnEnabled()) {
160 _log.warn(
161 "This URL can only be invoked using POST: " +
162 currentURL);
163 }
164
165 throw new PrincipalException(currentURL);
166 }
167 }
168
169 portletAction.processAction(
170 actionMapping, actionForm, liferayPortletConfig, actionRequest,
171 actionResponse);
172 }
173 catch (Exception e) {
174 String exceptionId =
175 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
176 liferayPortletConfig.getPortletId();
177
178 actionRequest.setAttribute(exceptionId, e);
179 }
180
181 String forward = (String)actionRequest.getAttribute(
182 PortletAction.getForwardKey(actionRequest));
183
184 if (forward == null) {
185 return;
186 }
187
188 String queryString = StringPool.BLANK;
189
190 int pos = forward.indexOf(CharPool.QUESTION);
191
192 if (pos != -1) {
193 queryString = forward.substring(pos + 1);
194 forward = forward.substring(0, pos);
195 }
196
197 ActionForward actionForward = actionMapping.findForward(forward);
198
199 if ((actionForward != null) && actionForward.getRedirect()) {
200 String forwardPath = actionForward.getPath();
201
202 if (forwardPath.startsWith(StringPool.SLASH)) {
203 LiferayPortletURL forwardURL =
204 (LiferayPortletURL)actionResponseImpl.createRenderURL();
205
206 forwardURL.setParameter("struts_action", forwardPath);
207
208 StrutsURLEncoder.setParameters(forwardURL, queryString);
209
210 forwardPath = forwardURL.toString();
211 }
212
213 actionResponse.sendRedirect(forwardPath);
214 }
215 }
216
217 public void process(
218 RenderRequest renderRequest, RenderResponse renderResponse)
219 throws IOException, ServletException {
220
221 HttpServletRequest request = PortalUtil.getHttpServletRequest(
222 renderRequest);
223 HttpServletResponse response = PortalUtil.getHttpServletResponse(
224 renderResponse);
225
226 process(request, response);
227 }
228
229 public void process(
230 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
231 throws IOException, ServletException {
232
233 HttpServletRequest request = PortalUtil.getHttpServletRequest(
234 resourceRequest);
235 HttpServletResponse response = PortalUtil.getHttpServletResponse(
236 resourceResponse);
237
238 process(request, response);
239 }
240
241 @Override
242 public ActionMapping processMapping(
243 HttpServletRequest request, HttpServletResponse response, String path) {
244
245 if (path == null) {
246 return null;
247 }
248
249 ActionMapping actionMapping = null;
250
251 long companyId = PortalUtil.getCompanyId(request);
252
253 LiferayPortletConfig liferayPortletConfig =
254 (LiferayPortletConfig)request.getAttribute(
255 JavaConstants.JAVAX_PORTLET_CONFIG);
256
257 try {
258 Portlet portlet = PortletLocalServiceUtil.getPortletById(
259 companyId, liferayPortletConfig.getPortletId());
260
261 if (StrutsActionRegistryUtil.getAction(path) != null) {
262 actionMapping = (ActionMapping)moduleConfig.findActionConfig(
263 path);
264
265 if (actionMapping == null) {
266 actionMapping = new ActionMapping();
267
268 actionMapping.setModuleConfig(moduleConfig);
269 actionMapping.setPath(path);
270
271 request.setAttribute(Globals.MAPPING_KEY, actionMapping);
272 }
273 }
274 else if (moduleConfig.findActionConfig(path) != null) {
275 actionMapping = super.processMapping(request, response, path);
276 }
277 else if (Validator.isNotNull(portlet.getParentStrutsPath())) {
278 int pos = path.indexOf(StringPool.SLASH, 1);
279
280 String parentPath =
281 StringPool.SLASH + portlet.getParentStrutsPath() +
282 path.substring(pos);
283
284 if (StrutsActionRegistryUtil.getAction(parentPath) != null) {
285 actionMapping =
286 (ActionMapping)moduleConfig.findActionConfig(
287 parentPath);
288
289 if (actionMapping == null) {
290 actionMapping = new ActionMapping();
291
292 actionMapping.setModuleConfig(moduleConfig);
293 actionMapping.setPath(parentPath);
294
295 request.setAttribute(
296 Globals.MAPPING_KEY, actionMapping);
297 }
298 }
299 else if (moduleConfig.findActionConfig(parentPath) != null) {
300 actionMapping = super.processMapping(
301 request, response, parentPath);
302 }
303 }
304 }
305 catch (Exception e) {
306 }
307
308 if (actionMapping == null) {
309 MessageResources messageResources = getInternal();
310
311 String msg = messageResources.getMessage("processInvalid");
312
313 _log.error("User ID " + request.getRemoteUser());
314 _log.error("Current URL " + PortalUtil.getCurrentURL(request));
315 _log.error("Referer " + request.getHeader("Referer"));
316 _log.error("Remote address " + request.getRemoteAddr());
317
318 _log.error(msg + " " + path);
319 }
320
321 return actionMapping;
322 }
323
324 @Override
325 protected void doForward(
326 String uri, HttpServletRequest request,
327 HttpServletResponse response)
328 throws IOException, ServletException {
329
330 doInclude(uri, request, response);
331 }
332
333 @Override
334 protected void doInclude(
335 String uri, HttpServletRequest request,
336 HttpServletResponse response)
337 throws IOException, ServletException {
338
339 LiferayPortletConfig liferayPortletConfig =
340 (LiferayPortletConfig)request.getAttribute(
341 JavaConstants.JAVAX_PORTLET_CONFIG);
342
343 PortletContext portletContext =
344 liferayPortletConfig.getPortletContext();
345
346 PortletRequest portletRequest = (PortletRequest)request.getAttribute(
347 JavaConstants.JAVAX_PORTLET_REQUEST);
348
349 PortletResponse portletResponse = (PortletResponse)request.getAttribute(
350 JavaConstants.JAVAX_PORTLET_RESPONSE);
351
352 LiferayPortletRequestDispatcher liferayPortletRequestDispatcher =
353 (LiferayPortletRequestDispatcher)
354 portletContext.getRequestDispatcher(
355 StrutsUtil.TEXT_HTML_DIR + uri);
356
357 try {
358 if (liferayPortletRequestDispatcher == null) {
359 _log.error(uri + " is not a valid include");
360 }
361 else {
362 liferayPortletRequestDispatcher.include(
363 portletRequest, portletResponse, true);
364 }
365 }
366 catch (PortletException pe) {
367 Throwable cause = pe.getCause();
368
369 if (cause instanceof ServletException) {
370 throw (ServletException)cause;
371 }
372 else {
373 _log.error(cause, cause);
374 }
375 }
376 }
377
378 @Override
379 protected Action processActionCreate(
380 HttpServletRequest request, HttpServletResponse response,
381 ActionMapping actionMapping)
382 throws IOException {
383
384 PortletActionAdapter portletActionAdapter =
385 (PortletActionAdapter)StrutsActionRegistryUtil.getAction(
386 actionMapping.getPath());
387
388 if (portletActionAdapter != null) {
389 ActionConfig actionConfig = moduleConfig.findActionConfig(
390 actionMapping.getPath());
391
392 if (actionConfig != null) {
393 PortletAction originalPortletAction =
394 (PortletAction)super.processActionCreate(
395 request, response, actionMapping);
396
397 portletActionAdapter.setOriginalPortletAction(
398 originalPortletAction);
399 }
400
401 return portletActionAdapter;
402 }
403
404 return super.processActionCreate(request, response, actionMapping);
405 }
406
407 @Override
408 protected ActionForm processActionForm(
409 HttpServletRequest request, HttpServletResponse response,
410 ActionMapping actionMapping) {
411
412 ActionForm actionForm = super.processActionForm(
413 request, response, actionMapping);
414
415 if (actionForm instanceof InitializableActionForm) {
416 InitializableActionForm initializableActionForm =
417 (InitializableActionForm)actionForm;
418
419 initializableActionForm.init(request, response, actionMapping);
420 }
421
422 return actionForm;
423 }
424
425 @Override
426 protected ActionForward processActionPerform(
427 HttpServletRequest request, HttpServletResponse response,
428 Action action, ActionForm actionForm, ActionMapping actionMapping)
429 throws IOException, ServletException {
430
431 LiferayPortletConfig liferayPortletConfig =
432 (LiferayPortletConfig)request.getAttribute(
433 JavaConstants.JAVAX_PORTLET_CONFIG);
434
435 String exceptionId =
436 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
437 liferayPortletConfig.getPortletId();
438
439 Exception e = (Exception)request.getAttribute(exceptionId);
440
441 if (e != null) {
442 return processException(
443 request, response, e, actionForm, actionMapping);
444 }
445 else {
446 return super.processActionPerform(
447 request, response, action, actionForm, actionMapping);
448 }
449 }
450
451 @Override
452 protected void processForwardConfig(
453 HttpServletRequest request, HttpServletResponse response,
454 ForwardConfig forward)
455 throws IOException, ServletException {
456
457 if (forward == null) {
458 _log.error("Forward does not exist");
459 }
460 else {
461
462
463
464
465 if (forward.getPath().equals(ActionConstants.COMMON_NULL)) {
466 return;
467 }
468 }
469
470 super.processForwardConfig(request, response, forward);
471 }
472
473 @Override
474 protected HttpServletRequest processMultipart(HttpServletRequest request) {
475
476
477
478 return request;
479 }
480
481 @Override
482 protected String processPath(
483 HttpServletRequest request, HttpServletResponse response) {
484
485 String path = request.getParameter("struts_action");
486
487 if (_log.isDebugEnabled()) {
488 _log.debug("Getting request parameter path " + path);
489 }
490
491 if (Validator.isNull(path)) {
492 if (_log.isDebugEnabled()) {
493 _log.debug("Getting request attribute path " + path);
494 }
495
496 path = (String)request.getAttribute(WebKeys.PORTLET_STRUTS_ACTION);
497 }
498
499 if (path == null) {
500 LiferayPortletConfig liferayPortletConfig =
501 (LiferayPortletConfig)request.getAttribute(
502 JavaConstants.JAVAX_PORTLET_CONFIG);
503
504 _log.error(
505 liferayPortletConfig.getPortletName() +
506 " does not have any paths specified");
507 }
508 else {
509 if (_log.isDebugEnabled()) {
510 _log.debug("Processing path " + path);
511 }
512 }
513
514 return path;
515 }
516
517 @Override
518 protected boolean processRoles(
519 HttpServletRequest request, HttpServletResponse response,
520 ActionMapping actionMapping)
521 throws IOException, ServletException {
522
523 return processRoles(request, response, actionMapping, false);
524 }
525
526 protected boolean processRoles(
527 HttpServletRequest request, HttpServletResponse response,
528 ActionMapping actionMapping, boolean action)
529 throws IOException, ServletException {
530
531 long companyId = PortalUtil.getCompanyId(request);
532
533 String path = actionMapping.getPath();
534
535 try {
536 LiferayPortletConfig liferayPortletConfig =
537 (LiferayPortletConfig)request.getAttribute(
538 JavaConstants.JAVAX_PORTLET_CONFIG);
539
540 Portlet portlet = PortletLocalServiceUtil.getPortletById(
541 companyId, liferayPortletConfig.getPortletId());
542
543 if (portlet == null) {
544 return false;
545 }
546
547 String strutsPath = path.substring(
548 1, path.lastIndexOf(CharPool.SLASH));
549
550 if (!strutsPath.equals(portlet.getStrutsPath()) &&
551 !strutsPath.equals(portlet.getParentStrutsPath())) {
552
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 }