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