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