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