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