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