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