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