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