1
22
23 package com.liferay.portal.struts;
24
25 import com.liferay.portal.kernel.log.Log;
26 import com.liferay.portal.kernel.log.LogFactoryUtil;
27 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
28 import com.liferay.portal.kernel.util.JavaConstants;
29 import com.liferay.portal.kernel.util.StringPool;
30 import com.liferay.portal.kernel.util.Validator;
31 import com.liferay.portal.model.Layout;
32 import com.liferay.portal.model.Portlet;
33 import com.liferay.portal.model.User;
34 import com.liferay.portal.security.auth.PrincipalException;
35 import com.liferay.portal.security.permission.ActionKeys;
36 import com.liferay.portal.security.permission.PermissionChecker;
37 import com.liferay.portal.service.PortletLocalServiceUtil;
38 import com.liferay.portal.service.permission.PortletPermissionUtil;
39 import com.liferay.portal.theme.ThemeDisplay;
40 import com.liferay.portal.util.PortalUtil;
41 import com.liferay.portal.util.PropsValues;
42 import com.liferay.portal.util.WebKeys;
43 import com.liferay.portlet.ActionResponseImpl;
44 import com.liferay.portlet.PortletConfigImpl;
45 import com.liferay.portlet.PortletRequestDispatcherImpl;
46
47 import java.io.IOException;
48
49 import java.lang.reflect.Constructor;
50
51 import javax.portlet.ActionRequest;
52 import javax.portlet.ActionResponse;
53 import javax.portlet.PortletContext;
54 import javax.portlet.PortletException;
55 import javax.portlet.PortletRequest;
56 import javax.portlet.PortletResponse;
57 import javax.portlet.RenderRequest;
58 import javax.portlet.RenderResponse;
59 import javax.portlet.ResourceRequest;
60 import javax.portlet.ResourceResponse;
61
62 import javax.servlet.ServletException;
63 import javax.servlet.http.HttpServletRequest;
64 import javax.servlet.http.HttpServletResponse;
65
66 import org.apache.struts.Globals;
67 import org.apache.struts.action.Action;
68 import org.apache.struts.action.ActionErrors;
69 import org.apache.struts.action.ActionForm;
70 import org.apache.struts.action.ActionForward;
71 import org.apache.struts.action.ActionMapping;
72 import org.apache.struts.action.ActionServlet;
73 import org.apache.struts.config.ForwardConfig;
74 import org.apache.struts.config.ModuleConfig;
75 import org.apache.struts.tiles.TilesRequestProcessor;
76
77
82 public class PortletRequestProcessor extends TilesRequestProcessor {
83
84 public static PortletRequestProcessor getInstance(
85 ActionServlet servlet, ModuleConfig moduleConfig)
86 throws ServletException {
87
88 try {
89 String className = PropsValues.STRUTS_PORTLET_REQUEST_PROCESSOR;
90
91 Class<?> clazz = Class.forName(className);
92
93 Constructor<?> constructor = clazz.getConstructor(
94 new Class[] {
95 ActionServlet.class, ModuleConfig.class
96 }
97 );
98
99 PortletRequestProcessor portletReqProcessor =
100 (PortletRequestProcessor)constructor.newInstance(
101 new Object[] {
102 servlet, moduleConfig
103 }
104 );
105
106 return portletReqProcessor;
107 }
108 catch (Exception e) {
109 _log.error(e);
110
111 return new PortletRequestProcessor(servlet, moduleConfig);
112 }
113 }
114
115 public PortletRequestProcessor(
116 ActionServlet actionServlet, ModuleConfig moduleConfig)
117 throws ServletException {
118
119 init(actionServlet, moduleConfig);
120 }
121
122 public void process(
123 ActionRequest actionRequest, ActionResponse actionResponse,
124 String path)
125 throws IOException, ServletException {
126
127 ActionResponseImpl actionResponseImpl =
128 (ActionResponseImpl)actionResponse;
129
130 HttpServletRequest request = PortalUtil.getHttpServletRequest(
131 actionRequest);
132 HttpServletResponse response = PortalUtil.getHttpServletResponse(
133 actionResponse);
134
135 ActionMapping mapping = processMapping(request, response, path);
136
137 if (mapping == null) {
138 return;
139 }
140
141 if (!processRoles(request, response, mapping, true)) {
142 return;
143 }
144
145 ActionForm form = processActionForm(request, response, mapping);
146
147 processPopulate(request, response, form, mapping);
148
149 if (!processValidateAction(request, response, form, mapping)) {
150 return;
151 }
152
153 PortletAction action =
154 (PortletAction)processActionCreate(request, response, mapping);
155
156 if (action == null) {
157 return;
158 }
159
160 PortletConfigImpl portletConfigImpl =
161 (PortletConfigImpl)actionRequest.getAttribute(
162 JavaConstants.JAVAX_PORTLET_CONFIG);
163
164 try {
165 if (action.isCheckMethodOnProcessAction()) {
166 if (!PortalUtil.isMethodPost(actionRequest)) {
167 String currentURL = PortalUtil.getCurrentURL(actionRequest);
168
169 if (_log.isWarnEnabled()) {
170 _log.warn(
171 "This URL can only be invoked using POST: " +
172 currentURL);
173 }
174
175 throw new PrincipalException(currentURL);
176 }
177 }
178
179 action.processAction(
180 mapping, form, portletConfigImpl, actionRequest,
181 actionResponse);
182 }
183 catch (Exception e) {
184 String exceptionId =
185 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
186 portletConfigImpl.getPortletId();
187
188 actionRequest.setAttribute(exceptionId, e);
189 }
190
191 String forward = (String)actionRequest.getAttribute(
192 PortletAction.getForwardKey(actionRequest));
193
194 if (forward != null) {
195 String queryString = StringPool.BLANK;
196
197 int pos = forward.indexOf(StringPool.QUESTION);
198
199 if (pos != -1) {
200 queryString = forward.substring(pos + 1, forward.length());
201 forward = forward.substring(0, pos);
202 }
203
204 ActionForward actionForward = mapping.findForward(forward);
205
206 if ((actionForward != null) && (actionForward.getRedirect())) {
207 String forwardPath = actionForward.getPath();
208
209 if (forwardPath.startsWith(StringPool.SLASH)) {
210 LiferayPortletURL forwardURL =
211 (LiferayPortletURL)actionResponseImpl.createRenderURL();
212
213 forwardURL.setParameter("struts_action", forwardPath);
214
215 StrutsURLEncoder.setParameters(forwardURL, queryString);
216
217 forwardPath = forwardURL.toString();
218 }
219
220 actionResponse.sendRedirect(forwardPath);
221 }
222 }
223 }
224
225 public void process(
226 RenderRequest renderRequest, RenderResponse renderResponse)
227 throws IOException, ServletException {
228
229 HttpServletRequest request = PortalUtil.getHttpServletRequest(
230 renderRequest);
231 HttpServletResponse response = PortalUtil.getHttpServletResponse(
232 renderResponse);
233
234 process(request, response);
235 }
236
237 public void process(
238 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
239 throws IOException, ServletException {
240
241 HttpServletRequest request = PortalUtil.getHttpServletRequest(
242 resourceRequest);
243 HttpServletResponse response = PortalUtil.getHttpServletResponse(
244 resourceResponse);
245
246 process(request, response);
247 }
248
249 protected void doForward(
250 String uri, HttpServletRequest request,
251 HttpServletResponse response)
252 throws IOException, ServletException {
253
254 doInclude(uri, request, response);
255 }
256
257 protected void doInclude(
258 String uri, HttpServletRequest request,
259 HttpServletResponse response)
260 throws IOException, ServletException {
261
262 PortletConfigImpl portletConfig =
263 (PortletConfigImpl)request.getAttribute(
264 JavaConstants.JAVAX_PORTLET_CONFIG);
265
266 PortletContext portletContext = portletConfig.getPortletContext();
267
268 PortletRequest portletRequest = (PortletRequest)request.getAttribute(
269 JavaConstants.JAVAX_PORTLET_REQUEST);
270
271 PortletResponse portletResponse = (PortletResponse)request.getAttribute(
272 JavaConstants.JAVAX_PORTLET_RESPONSE);
273
274 PortletRequestDispatcherImpl portletRequestDispatcher =
275 (PortletRequestDispatcherImpl)portletContext.getRequestDispatcher(
276 StrutsUtil.TEXT_HTML_DIR + uri);
277
278 try {
279 if (portletRequestDispatcher == null) {
280 _log.error(uri + " is not a valid include");
281 }
282 else {
283 portletRequestDispatcher.include(
284 portletRequest, portletResponse, true);
285 }
286 }
287 catch (PortletException pe) {
288 Throwable cause = pe.getCause();
289
290 if (cause instanceof ServletException) {
291 throw (ServletException)cause;
292 }
293 else {
294 _log.error(cause, cause);
295 }
296 }
297 }
298
299 protected ActionForm processActionForm(
300 HttpServletRequest request, HttpServletResponse response,
301 ActionMapping mapping) {
302
303 ActionForm form = super.processActionForm(request, response, mapping);
304
305 if (form instanceof InitializableActionForm) {
306 InitializableActionForm initForm = (InitializableActionForm)form;
307
308 initForm.init(request, response, mapping);
309 }
310
311 return form;
312 }
313
314 protected ActionForward processActionPerform(
315 HttpServletRequest request, HttpServletResponse response,
316 Action action, ActionForm form, ActionMapping mapping)
317 throws IOException, ServletException {
318
319 PortletConfigImpl portletConfig =
320 (PortletConfigImpl)request.getAttribute(
321 JavaConstants.JAVAX_PORTLET_CONFIG);
322
323 String exceptionId =
324 WebKeys.PORTLET_STRUTS_EXCEPTION + StringPool.PERIOD +
325 portletConfig.getPortletId();
326
327 Exception e = (Exception)request.getAttribute(exceptionId);
328
329 if (e != null) {
330 return processException(request, response, e, form, mapping);
331 }
332 else {
333 return super.processActionPerform(
334 request, response, action, form, mapping);
335 }
336 }
337
338 protected void processForwardConfig(
339 HttpServletRequest request, HttpServletResponse response,
340 ForwardConfig forward)
341 throws IOException, ServletException {
342
343 if (forward == null) {
344 _log.error("Forward does not exist");
345 }
346 else {
347
348
351 if (forward.getPath().equals(ActionConstants.COMMON_NULL)) {
352 return;
353 }
354 }
355
356 super.processForwardConfig(request, response, forward);
357 }
358
359 public ActionMapping processMapping(
360 HttpServletRequest request, HttpServletResponse response,
361 String path)
362 throws IOException {
363
364 if (path == null) {
365 return null;
366 }
367
368 ActionMapping mapping = super.processMapping(request, response, path);
369
370 if (mapping == null) {
371 String msg = getInternal().getMessage("processInvalid");
372
373 _log.error("User ID " + request.getRemoteUser());
374 _log.error("Current URL " + PortalUtil.getCurrentURL(request));
375 _log.error("Referer " + request.getHeader("Referer"));
376 _log.error("Remote address " + request.getRemoteAddr());
377
378 _log.error(msg + " " + path);
379 }
380
381 return mapping;
382 }
383
384 protected HttpServletRequest processMultipart(HttpServletRequest request) {
385
386
388 return request;
389 }
390
391 protected String processPath(
392 HttpServletRequest request, HttpServletResponse response) {
393
394 String path = request.getParameter("struts_action");
395
396 if (_log.isDebugEnabled()) {
397 _log.debug("Getting request parameter path " + path);
398 }
399
400 if (Validator.isNull(path)) {
401 if (_log.isDebugEnabled()) {
402 _log.debug("Getting request attribute path " + path);
403 }
404
405 path = (String)request.getAttribute(WebKeys.PORTLET_STRUTS_ACTION);
406 }
407
408 if (path == null) {
409 PortletConfigImpl portletConfig =
410 (PortletConfigImpl)request.getAttribute(
411 JavaConstants.JAVAX_PORTLET_CONFIG);
412
413 _log.error(
414 portletConfig.getPortletName() +
415 " does not have any paths specified");
416 }
417 else {
418 if (_log.isDebugEnabled()) {
419 _log.debug("Processing path " + path);
420 }
421 }
422
423 return path;
424 }
425
426 protected boolean processRoles(
427 HttpServletRequest request, HttpServletResponse response,
428 ActionMapping mapping)
429 throws IOException, ServletException {
430
431 return processRoles(request, response, mapping, false);
432 }
433
434 protected boolean processRoles(
435 HttpServletRequest request, HttpServletResponse response,
436 ActionMapping mapping, boolean action)
437 throws IOException, ServletException {
438
439 User user = null;
440
441 try {
442 user = PortalUtil.getUser(request);
443 }
444 catch (Exception e) {
445 }
446
447 if (user == null) {
448 return true;
449 }
450
451 String path = mapping.getPath();
452
453 try {
454 PortletConfigImpl portletConfig =
455 (PortletConfigImpl)request.getAttribute(
456 JavaConstants.JAVAX_PORTLET_CONFIG);
457
458 Portlet portlet = PortletLocalServiceUtil.getPortletById(
459 user.getCompanyId(), portletConfig.getPortletId());
460
461 if (portlet == null) {
462 return false;
463 }
464
465 String strutsPath = path.substring(
466 1, path.lastIndexOf(StringPool.SLASH));
467
468 if (!strutsPath.equals(portlet.getStrutsPath())) {
469 if (_log.isWarnEnabled()) {
470 _log.warn(
471 "The struts path " + strutsPath + " does not belong " +
472 "to portlet " + portlet.getPortletId() + ". " +
473 "Check the definition in liferay-portlet.xml");
474 }
475
476 throw new PrincipalException();
477 }
478 else if (portlet.isActive()) {
479 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
480 WebKeys.THEME_DISPLAY);
481
482 Layout layout = themeDisplay.getLayout();
483 PermissionChecker permissionChecker =
484 themeDisplay.getPermissionChecker();
485
486 if (!PortletPermissionUtil.contains(
487 permissionChecker, layout.getPlid(), portlet,
488 ActionKeys.VIEW)) {
489
490 throw new PrincipalException();
491 }
492 }
493 else if (!portlet.isActive()) {
494 ForwardConfig forwardConfig =
495 mapping.findForward(_PATH_PORTAL_PORTLET_INACTIVE);
496
497 if (!action) {
498 processForwardConfig(request, response, forwardConfig);
499 }
500
501 return false;
502 }
503 }
504 catch (Exception e) {
505 if (_log.isWarnEnabled()) {
506 _log.warn(e.getMessage());
507 }
508
509 ForwardConfig forwardConfig =
510 mapping.findForward(_PATH_PORTAL_PORTLET_ACCESS_DENIED);
511
512 if (!action) {
513 processForwardConfig(request, response, forwardConfig);
514 }
515
516 return false;
517 }
518
519 return true;
520 }
521
522 protected boolean processValidateAction(
523 HttpServletRequest request, HttpServletResponse response,
524 ActionForm form, ActionMapping mapping) {
525
526 if (form == null) {
527 return true;
528 }
529
530 if (request.getAttribute(Globals.CANCEL_KEY) != null) {
531 return true;
532 }
533
534 if (!mapping.getValidate()) {
535 return true;
536 }
537
538 ActionErrors errors = form.validate(mapping, request);
539
540 if ((errors == null) || errors.isEmpty()) {
541 return true;
542 }
543
544 if (form.getMultipartRequestHandler() != null) {
545 form.getMultipartRequestHandler().rollback();
546 }
547
548 String input = mapping.getInput();
549
550 if (input == null) {
551 _log.error("Validation failed but no input form is available");
552
553 return false;
554 }
555
556 request.setAttribute(Globals.ERROR_KEY, errors);
557
558
561 request.setAttribute(PortletAction.getForwardKey(request), input);
562
563 return false;
564 }
565
566 private static final String _PATH_PORTAL_PORTLET_ACCESS_DENIED =
567 "/portal/portlet_access_denied";
568
569 private static final String _PATH_PORTAL_PORTLET_INACTIVE =
570 "/portal/portlet_inactive";
571
572 private static Log _log =
573 LogFactoryUtil.getLog(PortletRequestProcessor.class);
574
575 }