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