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 String mvcRenderCommandName = ParamUtil.getString(
261 renderRequest, "mvcRenderCommandName", "/");
262
263 String mvcPath = ParamUtil.getString(renderRequest, "mvcPath");
264
265 if (!mvcRenderCommandName.equals("/") || Validator.isNull(mvcPath)) {
266 MVCRenderCommand mvcRenderCommand =
267 (MVCRenderCommand)_mvcRenderCommandCache.getMVCCommand(
268 mvcRenderCommandName);
269
270 mvcPath = null;
271
272 if (mvcRenderCommand != MVCRenderCommand.EMPTY) {
273 mvcPath = mvcRenderCommand.render(
274 renderRequest, renderResponse);
275 }
276
277 renderRequest.setAttribute(
278 getMVCPathAttributeName(renderResponse.getNamespace()),
279 mvcPath);
280 }
281
282 super.render(renderRequest, renderResponse);
283 }
284
285 @Override
286 public void serveResource(
287 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
288 throws IOException, PortletException {
289
290 String path = getPath(resourceRequest, resourceResponse);
291
292 if (path != null) {
293 include(
294 path, resourceRequest, resourceResponse,
295 PortletRequest.RESOURCE_PHASE);
296 }
297
298 boolean invokeTaglibDiscussion = GetterUtil.getBoolean(
299 resourceRequest.getParameter("invokeTaglibDiscussion"));
300
301 if (invokeTaglibDiscussion) {
302 invokeTaglibDiscussionPagination(resourceRequest, resourceResponse);
303 }
304 else {
305 super.serveResource(resourceRequest, resourceResponse);
306 }
307 }
308
309 @Override
310 protected boolean callActionMethod(
311 ActionRequest actionRequest, ActionResponse actionResponse)
312 throws PortletException {
313
314 try {
315 checkPermissions(actionRequest);
316 }
317 catch (Exception e) {
318 throw new PortletException(e);
319 }
320
321 String[] actionNames = ParamUtil.getParameterValues(
322 actionRequest, ActionRequest.ACTION_NAME);
323
324 String actionName = StringUtil.merge(actionNames);
325
326 if (!actionName.contains(StringPool.COMMA)) {
327 MVCActionCommand mvcActionCommand =
328 (MVCActionCommand)_mvcActionCommandCache.getMVCCommand(
329 actionName);
330
331 if (mvcActionCommand != MVCActionCommand.EMPTY) {
332 if (mvcActionCommand instanceof FormMVCActionCommand) {
333 FormMVCActionCommand formMVCActionCommand =
334 (FormMVCActionCommand)mvcActionCommand;
335
336 if (!formMVCActionCommand.validateForm(
337 actionRequest, actionResponse)) {
338
339 return false;
340 }
341 }
342
343 return mvcActionCommand.processAction(
344 actionRequest, actionResponse);
345 }
346 }
347 else {
348 List<MVCActionCommand> mvcActionCommands =
349 (List<MVCActionCommand>)_mvcActionCommandCache.getMVCCommands(
350 actionName);
351
352 if (!mvcActionCommands.isEmpty()) {
353 boolean valid = true;
354
355 for (MVCActionCommand mvcActionCommand : mvcActionCommands) {
356 if (mvcActionCommand instanceof FormMVCActionCommand) {
357 FormMVCActionCommand formMVCActionCommand =
358 (FormMVCActionCommand)mvcActionCommand;
359
360 valid &= formMVCActionCommand.validateForm(
361 actionRequest, actionResponse);
362 }
363 }
364
365 if (!valid) {
366 return false;
367 }
368
369 for (MVCActionCommand mvcActionCommand : mvcActionCommands) {
370 if (!mvcActionCommand.processAction(
371 actionRequest, actionResponse)) {
372
373 return false;
374 }
375 }
376
377 return true;
378 }
379 }
380
381 return super.callActionMethod(actionRequest, actionResponse);
382 }
383
384 @Override
385 protected boolean callResourceMethod(
386 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
387 throws PortletException {
388
389 try {
390 checkPermissions(resourceRequest);
391 }
392 catch (Exception e) {
393 throw new PortletException(e);
394 }
395
396 String resourceID = GetterUtil.getString(
397 resourceRequest.getResourceID());
398
399 if (!resourceID.contains(StringPool.COMMA)) {
400 MVCResourceCommand mvcResourceCommand =
401 (MVCResourceCommand)_mvcResourceCommandCache.getMVCCommand(
402 resourceID);
403
404 if (mvcResourceCommand != MVCResourceCommand.EMPTY) {
405 return mvcResourceCommand.serveResource(
406 resourceRequest, resourceResponse);
407 }
408 }
409 else {
410 List<MVCResourceCommand> mvcResourceCommands =
411 (List<MVCResourceCommand>)
412 _mvcResourceCommandCache.getMVCCommands(resourceID);
413
414 if (!mvcResourceCommands.isEmpty()) {
415 for (MVCResourceCommand mvcResourceCommand :
416 mvcResourceCommands) {
417
418 if (!mvcResourceCommand.serveResource(
419 resourceRequest, resourceResponse)) {
420
421 return false;
422 }
423 }
424
425 return true;
426 }
427 }
428
429 return super.callResourceMethod(resourceRequest, resourceResponse);
430 }
431
432 protected void checkPath(String path) throws PortletException {
433 if (Validator.isNotNull(path) &&
434 (!path.startsWith(templatePath) ||
435 !PortalUtil.isValidResourceId(path) ||
436 !Validator.isFilePath(path, false))) {
437
438 throw new PortletException(
439 "Path " + path + " is not accessible by this portlet");
440 }
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(_MVC_PATH);
477 }
478
479 protected String getPath(
480 PortletRequest portletRequest, PortletResponse portletResponse) {
481
482 String mvcPath = portletRequest.getParameter("mvcPath");
483
484 if (mvcPath == null) {
485 mvcPath = (String)portletRequest.getAttribute(
486 getMVCPathAttributeName(portletResponse.getNamespace()));
487 }
488
489
490
491 if (mvcPath == null) {
492 mvcPath = portletRequest.getParameter("jspPage");
493 }
494
495 return mvcPath;
496 }
497
498 protected void hideDefaultErrorMessage(PortletRequest portletRequest) {
499 SessionMessages.add(
500 portletRequest,
501 PortalUtil.getPortletId(portletRequest) +
502 SessionMessages.KEY_SUFFIX_HIDE_DEFAULT_ERROR_MESSAGE);
503 }
504
505 protected void hideDefaultSuccessMessage(PortletRequest portletRequest) {
506 SessionMessages.add(
507 portletRequest,
508 PortalUtil.getPortletId(portletRequest) +
509 SessionMessages.KEY_SUFFIX_HIDE_DEFAULT_SUCCESS_MESSAGE);
510 }
511
512 protected void include(
513 String path, ActionRequest actionRequest,
514 ActionResponse actionResponse)
515 throws IOException, PortletException {
516
517 include(
518 path, actionRequest, actionResponse, PortletRequest.ACTION_PHASE);
519 }
520
521 protected void include(
522 String path, EventRequest eventRequest, EventResponse eventResponse)
523 throws IOException, PortletException {
524
525 include(path, eventRequest, eventResponse, PortletRequest.EVENT_PHASE);
526 }
527
528 protected void include(
529 String path, PortletRequest portletRequest,
530 PortletResponse portletResponse, String lifecycle)
531 throws IOException, PortletException {
532
533 PortletContext portletContext = getPortletContext();
534
535 PortletRequestDispatcher portletRequestDispatcher =
536 portletContext.getRequestDispatcher(path);
537
538 if (portletRequestDispatcher == null) {
539 _log.error(path + " is not a valid include");
540 }
541 else {
542 checkPath(path);
543
544 portletRequestDispatcher.include(portletRequest, portletResponse);
545 }
546
547 if (clearRequestParameters) {
548 if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
549 portletResponse.setProperty(
550 "clear-request-parameters", Boolean.TRUE.toString());
551 }
552 }
553 }
554
555 protected void include(
556 String path, RenderRequest renderRequest,
557 RenderResponse renderResponse)
558 throws IOException, PortletException {
559
560 include(
561 path, renderRequest, renderResponse, PortletRequest.RENDER_PHASE);
562 }
563
564 protected void include(
565 String path, ResourceRequest resourceRequest,
566 ResourceResponse resourceResponse)
567 throws IOException, PortletException {
568
569 include(
570 path, resourceRequest, resourceResponse,
571 PortletRequest.RESOURCE_PHASE);
572 }
573
574 protected String aboutTemplate;
575 protected boolean clearRequestParameters;
576 protected String configTemplate;
577 protected boolean copyRequestParameters;
578 protected String editDefaultsTemplate;
579 protected String editGuestTemplate;
580 protected String editTemplate;
581 protected String helpTemplate;
582 protected String previewTemplate;
583 protected String printTemplate;
584 protected String templatePath;
585 protected String viewTemplate;
586
587 private String _getInitParameter(String name) {
588 String value = getInitParameter(name);
589
590 if (value != null) {
591 return value;
592 }
593
594
595
596 if (name.equals("template-path")) {
597 return getInitParameter("jsp-path");
598 }
599 else if (name.endsWith("-template")) {
600 name = name.substring(0, name.length() - 9) + "-jsp";
601
602 return getInitParameter(name);
603 }
604
605 return null;
606 }
607
608 private static final String _MVC_PATH =
609 MVCPortlet.class.getName() + "#MVC_PATH";
610
611 private static final Log _log = LogFactoryUtil.getLog(MVCPortlet.class);
612
613 private MVCCommandCache _mvcActionCommandCache;
614 private MVCCommandCache _mvcRenderCommandCache;
615 private MVCCommandCache _mvcResourceCommandCache;
616
617 }