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