001
014
015 package com.liferay.portal.kernel.portlet.bridges.mvc;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.portlet.LiferayPortlet;
020 import com.liferay.portal.kernel.servlet.SessionMessages;
021 import com.liferay.portal.kernel.util.GetterUtil;
022 import com.liferay.portal.kernel.util.ParamUtil;
023 import com.liferay.portal.kernel.util.PortalUtil;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.StringUtil;
026 import com.liferay.portal.kernel.util.Validator;
027 import com.liferay.portal.kernel.util.WebKeys;
028
029 import java.io.IOException;
030
031 import java.util.List;
032
033 import javax.portlet.ActionRequest;
034 import javax.portlet.ActionResponse;
035 import javax.portlet.EventRequest;
036 import javax.portlet.EventResponse;
037 import javax.portlet.PortletConfig;
038 import javax.portlet.PortletContext;
039 import javax.portlet.PortletException;
040 import javax.portlet.PortletPreferences;
041 import javax.portlet.PortletRequest;
042 import javax.portlet.PortletRequestDispatcher;
043 import javax.portlet.PortletResponse;
044 import javax.portlet.RenderRequest;
045 import javax.portlet.RenderResponse;
046 import javax.portlet.ResourceRequest;
047 import javax.portlet.ResourceResponse;
048 import javax.portlet.WindowState;
049
050 import javax.servlet.http.HttpServletRequest;
051
052
056 public class MVCPortlet extends LiferayPortlet {
057
058 @Override
059 public void destroy() {
060 super.destroy();
061
062 _mvcActionCommandCache.close();
063 _mvcRenderCommandCache.close();
064 _mvcResourceCommandCache.close();
065 }
066
067 @Override
068 public void doAbout(
069 RenderRequest renderRequest, RenderResponse renderResponse)
070 throws IOException, PortletException {
071
072 include(aboutTemplate, renderRequest, renderResponse);
073 }
074
075 @Override
076 public void doConfig(
077 RenderRequest renderRequest, RenderResponse renderResponse)
078 throws IOException, PortletException {
079
080 include(configTemplate, renderRequest, renderResponse);
081 }
082
083 @Override
084 public void doEdit(
085 RenderRequest renderRequest, RenderResponse renderResponse)
086 throws IOException, PortletException {
087
088 PortletPreferences portletPreferences = renderRequest.getPreferences();
089
090 if (portletPreferences == null) {
091 super.doEdit(renderRequest, renderResponse);
092 }
093 else {
094 include(editTemplate, renderRequest, renderResponse);
095 }
096 }
097
098 @Override
099 public void doEditDefaults(
100 RenderRequest renderRequest, RenderResponse renderResponse)
101 throws IOException, PortletException {
102
103 PortletPreferences portletPreferences = renderRequest.getPreferences();
104
105 if (portletPreferences == null) {
106 super.doEdit(renderRequest, renderResponse);
107 }
108 else {
109 include(editDefaultsTemplate, renderRequest, renderResponse);
110 }
111 }
112
113 @Override
114 public void doEditGuest(
115 RenderRequest renderRequest, RenderResponse renderResponse)
116 throws IOException, PortletException {
117
118 PortletPreferences portletPreferences = renderRequest.getPreferences();
119
120 if (portletPreferences == null) {
121 super.doEdit(renderRequest, renderResponse);
122 }
123 else {
124 include(editGuestTemplate, renderRequest, renderResponse);
125 }
126 }
127
128 @Override
129 public void doHelp(
130 RenderRequest renderRequest, RenderResponse renderResponse)
131 throws IOException, PortletException {
132
133 include(helpTemplate, renderRequest, renderResponse);
134 }
135
136 @Override
137 public void doPreview(
138 RenderRequest renderRequest, RenderResponse renderResponse)
139 throws IOException, PortletException {
140
141 include(previewTemplate, renderRequest, renderResponse);
142 }
143
144 @Override
145 public void doPrint(
146 RenderRequest renderRequest, RenderResponse renderResponse)
147 throws IOException, PortletException {
148
149 include(printTemplate, renderRequest, renderResponse);
150 }
151
152 @Override
153 public void doView(
154 RenderRequest renderRequest, RenderResponse renderResponse)
155 throws IOException, PortletException {
156
157 include(viewTemplate, renderRequest, renderResponse);
158 }
159
160 @Override
161 public void init() throws PortletException {
162 super.init();
163
164 templatePath = _getInitParameter("template-path");
165
166 if (Validator.isNull(templatePath)) {
167 templatePath = StringPool.SLASH;
168 }
169 else if (templatePath.contains(StringPool.BACK_SLASH) ||
170 templatePath.contains(StringPool.DOUBLE_SLASH) ||
171 templatePath.contains(StringPool.PERIOD) ||
172 templatePath.contains(StringPool.SPACE)) {
173
174 throw new PortletException(
175 "template-path " + templatePath + " has invalid characters");
176 }
177 else if (!templatePath.startsWith(StringPool.SLASH) ||
178 !templatePath.endsWith(StringPool.SLASH)) {
179
180 throw new PortletException(
181 "template-path " + templatePath +
182 " must start and end with a /");
183 }
184
185 aboutTemplate = _getInitParameter("about-template");
186 configTemplate = _getInitParameter("config-template");
187 editTemplate = _getInitParameter("edit-template");
188 editDefaultsTemplate = _getInitParameter("edit-defaults-template");
189 editGuestTemplate = _getInitParameter("edit-guest-template");
190 helpTemplate = _getInitParameter("help-template");
191 previewTemplate = _getInitParameter("preview-template");
192 printTemplate = _getInitParameter("print-template");
193 viewTemplate = _getInitParameter("view-template");
194
195 clearRequestParameters = GetterUtil.getBoolean(
196 getInitParameter("clear-request-parameters"));
197 copyRequestParameters = GetterUtil.getBoolean(
198 getInitParameter("copy-request-parameters"), true);
199
200 _mvcActionCommandCache = new MVCCommandCache(
201 MVCActionCommand.EMPTY,
202 getInitParameter("mvc-action-command-package-prefix"),
203 getPortletName(), MVCActionCommand.class, "ActionCommand");
204 _mvcRenderCommandCache = new MVCCommandCache(
205 MVCRenderCommand.EMPTY,
206 getInitParameter("mvc-render-command-package-prefix"),
207 getPortletName(), MVCRenderCommand.class, "RenderCommand");
208 _mvcResourceCommandCache = new MVCCommandCache(
209 MVCResourceCommand.EMPTY,
210 getInitParameter("mvc-resource-command-package-prefix"),
211 getPortletName(), MVCResourceCommand.class, "ResourceCommand");
212
213 initValidPaths(templatePath, ".jsp");
214 }
215
216
219 @Deprecated
220 public void invokeTaglibDiscussion(
221 ActionRequest actionRequest, ActionResponse actionResponse)
222 throws Exception {
223
224 PortletConfig portletConfig = getPortletConfig();
225
226 PortalUtil.invokeTaglibDiscussion(
227 portletConfig, actionRequest, actionResponse);
228 }
229
230
233 @Deprecated
234 public void invokeTaglibDiscussionPagination(
235 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
236 throws IOException, PortletException {
237
238 PortletConfig portletConfig = getPortletConfig();
239
240 PortalUtil.invokeTaglibDiscussionPagination(
241 portletConfig, resourceRequest, resourceResponse);
242 }
243
244 @Override
245 public void processAction(
246 ActionRequest actionRequest, ActionResponse actionResponse)
247 throws IOException, PortletException {
248
249 super.processAction(actionRequest, actionResponse);
250
251 if (copyRequestParameters) {
252 PortalUtil.copyRequestParameters(actionRequest, actionResponse);
253 }
254 }
255
256 @Override
257 public void render(
258 RenderRequest renderRequest, RenderResponse renderResponse)
259 throws IOException, PortletException {
260
261 invokeHideDefaultSuccessMessage(renderRequest);
262
263 String mvcRenderCommandName = ParamUtil.getString(
264 renderRequest, "mvcRenderCommandName", "/");
265
266 String mvcPath = ParamUtil.getString(renderRequest, "mvcPath");
267
268 if (!mvcRenderCommandName.equals("/") || Validator.isNull(mvcPath)) {
269 MVCRenderCommand mvcRenderCommand =
270 (MVCRenderCommand)_mvcRenderCommandCache.getMVCCommand(
271 mvcRenderCommandName);
272
273 mvcPath = null;
274
275 if (mvcRenderCommand != MVCRenderCommand.EMPTY) {
276 mvcPath = mvcRenderCommand.render(
277 renderRequest, renderResponse);
278 }
279
280 if (MVCRenderConstants.MVC_PATH_VALUE_SKIP_DISPATCH.equals(
281 mvcPath)) {
282
283 return;
284 }
285
286 renderRequest.setAttribute(
287 getMVCPathAttributeName(renderResponse.getNamespace()),
288 mvcPath);
289 }
290
291 super.render(renderRequest, renderResponse);
292 }
293
294 @Override
295 public void serveResource(
296 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
297 throws IOException, PortletException {
298
299 invokeHideDefaultSuccessMessage(resourceRequest);
300
301 String path = getPath(resourceRequest, resourceResponse);
302
303 if (path != null) {
304 include(
305 path, resourceRequest, resourceResponse,
306 PortletRequest.RESOURCE_PHASE);
307 }
308
309 boolean invokeTaglibDiscussion = GetterUtil.getBoolean(
310 resourceRequest.getParameter("invokeTaglibDiscussion"));
311
312 if (invokeTaglibDiscussion) {
313 invokeTaglibDiscussionPagination(resourceRequest, resourceResponse);
314 }
315 else {
316 super.serveResource(resourceRequest, resourceResponse);
317 }
318 }
319
320 @Override
321 protected boolean callActionMethod(
322 ActionRequest actionRequest, ActionResponse actionResponse)
323 throws PortletException {
324
325 try {
326 checkPermissions(actionRequest);
327 }
328 catch (Exception e) {
329 throw new PortletException(e);
330 }
331
332 String[] actionNames = ParamUtil.getParameterValues(
333 actionRequest, ActionRequest.ACTION_NAME);
334
335 String actionName = StringUtil.merge(actionNames);
336
337 if (!actionName.contains(StringPool.COMMA)) {
338 MVCActionCommand mvcActionCommand =
339 (MVCActionCommand)_mvcActionCommandCache.getMVCCommand(
340 actionName);
341
342 if (mvcActionCommand != MVCActionCommand.EMPTY) {
343 if (mvcActionCommand instanceof FormMVCActionCommand) {
344 FormMVCActionCommand formMVCActionCommand =
345 (FormMVCActionCommand)mvcActionCommand;
346
347 if (!formMVCActionCommand.validateForm(
348 actionRequest, actionResponse)) {
349
350 return false;
351 }
352 }
353
354 return mvcActionCommand.processAction(
355 actionRequest, actionResponse);
356 }
357 }
358 else {
359 List<MVCActionCommand> mvcActionCommands =
360 (List<MVCActionCommand>)_mvcActionCommandCache.getMVCCommands(
361 actionName);
362
363 if (!mvcActionCommands.isEmpty()) {
364 boolean valid = true;
365
366 for (MVCActionCommand mvcActionCommand : mvcActionCommands) {
367 if (mvcActionCommand instanceof FormMVCActionCommand) {
368 FormMVCActionCommand formMVCActionCommand =
369 (FormMVCActionCommand)mvcActionCommand;
370
371 valid &= formMVCActionCommand.validateForm(
372 actionRequest, actionResponse);
373 }
374 }
375
376 if (!valid) {
377 return false;
378 }
379
380 for (MVCActionCommand mvcActionCommand : mvcActionCommands) {
381 if (!mvcActionCommand.processAction(
382 actionRequest, actionResponse)) {
383
384 return false;
385 }
386 }
387
388 return true;
389 }
390 }
391
392 return super.callActionMethod(actionRequest, actionResponse);
393 }
394
395 @Override
396 protected boolean callResourceMethod(
397 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
398 throws PortletException {
399
400 try {
401 checkPermissions(resourceRequest);
402 }
403 catch (Exception e) {
404 throw new PortletException(e);
405 }
406
407 String resourceID = GetterUtil.getString(
408 resourceRequest.getResourceID());
409
410 if (!resourceID.contains(StringPool.COMMA)) {
411 MVCResourceCommand mvcResourceCommand =
412 (MVCResourceCommand)_mvcResourceCommandCache.getMVCCommand(
413 resourceID);
414
415 if (mvcResourceCommand != MVCResourceCommand.EMPTY) {
416 return mvcResourceCommand.serveResource(
417 resourceRequest, resourceResponse);
418 }
419 }
420 else {
421 List<MVCResourceCommand> mvcResourceCommands =
422 (List<MVCResourceCommand>)
423 _mvcResourceCommandCache.getMVCCommands(resourceID);
424
425 if (!mvcResourceCommands.isEmpty()) {
426 for (MVCResourceCommand mvcResourceCommand :
427 mvcResourceCommands) {
428
429 if (!mvcResourceCommand.serveResource(
430 resourceRequest, resourceResponse)) {
431
432 return false;
433 }
434 }
435
436 return true;
437 }
438 }
439
440 return super.callResourceMethod(resourceRequest, resourceResponse);
441 }
442
443 protected void checkPermissions(PortletRequest portletRequest)
444 throws Exception {
445 }
446
447 @Override
448 protected void doDispatch(
449 RenderRequest renderRequest, RenderResponse renderResponse)
450 throws IOException, PortletException {
451
452 String path = getPath(renderRequest, renderResponse);
453
454 if (path != null) {
455 if (!isProcessRenderRequest(renderRequest)) {
456 renderRequest.setAttribute(
457 WebKeys.PORTLET_DECORATE, Boolean.FALSE);
458
459 return;
460 }
461
462 WindowState windowState = renderRequest.getWindowState();
463
464 if (windowState.equals(WindowState.MINIMIZED)) {
465 return;
466 }
467
468 include(path, renderRequest, renderResponse);
469 }
470 else {
471 super.doDispatch(renderRequest, renderResponse);
472 }
473 }
474
475 protected String getMVCPathAttributeName(String namespace) {
476 return namespace.concat(StringPool.PERIOD).concat(
477 MVCRenderConstants.MVC_PATH_REQUEST_ATTRIBUTE_NAME);
478 }
479
480 protected String getPath(
481 PortletRequest portletRequest, PortletResponse portletResponse) {
482
483 String mvcPath = portletRequest.getParameter("mvcPath");
484
485 if (mvcPath == null) {
486 mvcPath = (String)portletRequest.getAttribute(
487 getMVCPathAttributeName(portletResponse.getNamespace()));
488 }
489
490
491
492 if (mvcPath == null) {
493 mvcPath = portletRequest.getParameter("jspPage");
494 }
495
496 return mvcPath;
497 }
498
499 protected void hideDefaultErrorMessage(PortletRequest portletRequest) {
500 SessionMessages.add(
501 portletRequest,
502 PortalUtil.getPortletId(portletRequest) +
503 SessionMessages.KEY_SUFFIX_HIDE_DEFAULT_ERROR_MESSAGE);
504 }
505
506 protected void hideDefaultSuccessMessage(PortletRequest portletRequest) {
507 SessionMessages.add(
508 portletRequest,
509 PortalUtil.getPortletId(portletRequest) +
510 SessionMessages.KEY_SUFFIX_HIDE_DEFAULT_SUCCESS_MESSAGE);
511 }
512
513 protected void include(
514 String path, ActionRequest actionRequest,
515 ActionResponse actionResponse)
516 throws IOException, PortletException {
517
518 include(
519 path, actionRequest, actionResponse, PortletRequest.ACTION_PHASE);
520 }
521
522 protected void include(
523 String path, EventRequest eventRequest, EventResponse eventResponse)
524 throws IOException, PortletException {
525
526 include(path, eventRequest, eventResponse, PortletRequest.EVENT_PHASE);
527 }
528
529 protected void include(
530 String path, PortletRequest portletRequest,
531 PortletResponse portletResponse, String lifecycle)
532 throws IOException, PortletException {
533
534 HttpServletRequest httpServletRequest =
535 PortalUtil.getHttpServletRequest(portletRequest);
536
537 PortletContext portletContext =
538 (PortletContext)httpServletRequest.getAttribute(
539 MVCRenderConstants.
540 PORTLET_CONTEXT_OVERRIDE_REQUEST_ATTIBUTE_NAME_PREFIX +
541 path);
542
543 if (portletContext == null) {
544 portletContext = getPortletContext();
545 }
546
547 PortletRequestDispatcher portletRequestDispatcher =
548 portletContext.getRequestDispatcher(path);
549
550 if (portletRequestDispatcher == null) {
551 _log.error(path + " is not a valid include");
552 }
553 else {
554 checkPath(path);
555
556 portletRequestDispatcher.include(portletRequest, portletResponse);
557 }
558
559 if (clearRequestParameters) {
560 if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
561 portletResponse.setProperty(
562 "clear-request-parameters", Boolean.TRUE.toString());
563 }
564 }
565 }
566
567 protected void include(
568 String path, RenderRequest renderRequest,
569 RenderResponse renderResponse)
570 throws IOException, PortletException {
571
572 include(
573 path, renderRequest, renderResponse, PortletRequest.RENDER_PHASE);
574 }
575
576 protected void include(
577 String path, ResourceRequest resourceRequest,
578 ResourceResponse resourceResponse)
579 throws IOException, PortletException {
580
581 include(
582 path, resourceRequest, resourceResponse,
583 PortletRequest.RESOURCE_PHASE);
584 }
585
586 protected void invokeHideDefaultSuccessMessage(
587 PortletRequest portletRequest) {
588
589 boolean hideDefaultSuccessMessage = ParamUtil.getBoolean(
590 portletRequest, "hideDefaultSuccessMessage");
591
592 if (hideDefaultSuccessMessage) {
593 hideDefaultSuccessMessage(portletRequest);
594 }
595 }
596
597 protected String aboutTemplate;
598 protected boolean clearRequestParameters;
599 protected String configTemplate;
600 protected boolean copyRequestParameters;
601 protected String editDefaultsTemplate;
602 protected String editGuestTemplate;
603 protected String editTemplate;
604 protected String helpTemplate;
605 protected String previewTemplate;
606 protected String printTemplate;
607 protected String templatePath;
608 protected String viewTemplate;
609
610 private String _getInitParameter(String name) {
611 String value = getInitParameter(name);
612
613 if (value != null) {
614 return value;
615 }
616
617
618
619 if (name.equals("template-path")) {
620 return getInitParameter("jsp-path");
621 }
622 else if (name.endsWith("-template")) {
623 name = name.substring(0, name.length() - 9) + "-jsp";
624
625 return getInitParameter(name);
626 }
627
628 return null;
629 }
630
631 private static final Log _log = LogFactoryUtil.getLog(MVCPortlet.class);
632
633 private MVCCommandCache _mvcActionCommandCache;
634 private MVCCommandCache _mvcRenderCommandCache;
635 private MVCCommandCache _mvcResourceCommandCache;
636
637 }