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