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