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