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