001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.util.GetterUtil;
021    import com.liferay.portal.kernel.util.ParamUtil;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.util.WebKeys;
025    import com.liferay.portal.util.PortalUtil;
026    
027    import java.io.IOException;
028    
029    import java.util.List;
030    
031    import javax.portlet.ActionRequest;
032    import javax.portlet.ActionResponse;
033    import javax.portlet.EventRequest;
034    import javax.portlet.EventResponse;
035    import javax.portlet.PortletConfig;
036    import javax.portlet.PortletContext;
037    import javax.portlet.PortletException;
038    import javax.portlet.PortletPreferences;
039    import javax.portlet.PortletRequest;
040    import javax.portlet.PortletRequestDispatcher;
041    import javax.portlet.PortletResponse;
042    import javax.portlet.RenderRequest;
043    import javax.portlet.RenderResponse;
044    import javax.portlet.ResourceRequest;
045    import javax.portlet.ResourceResponse;
046    import javax.portlet.WindowState;
047    
048    /**
049     * @author Brian Wing Shun Chan
050     * @author Raymond Aug??
051     */
052    public class MVCPortlet extends LiferayPortlet {
053    
054            @Override
055            public void destroy() {
056                    super.destroy();
057    
058                    _actionCommandCache.close();
059            }
060    
061            @Override
062            public void doAbout(
063                            RenderRequest renderRequest, RenderResponse renderResponse)
064                    throws IOException, PortletException {
065    
066                    include(aboutTemplate, renderRequest, renderResponse);
067            }
068    
069            @Override
070            public void doConfig(
071                            RenderRequest renderRequest, RenderResponse renderResponse)
072                    throws IOException, PortletException {
073    
074                    include(configTemplate, renderRequest, renderResponse);
075            }
076    
077            @Override
078            public void doEdit(
079                            RenderRequest renderRequest, RenderResponse renderResponse)
080                    throws IOException, PortletException {
081    
082                    PortletPreferences portletPreferences = renderRequest.getPreferences();
083    
084                    if (portletPreferences == null) {
085                            super.doEdit(renderRequest, renderResponse);
086                    }
087                    else {
088                            include(editTemplate, renderRequest, renderResponse);
089                    }
090            }
091    
092            @Override
093            public void doEditDefaults(
094                            RenderRequest renderRequest, RenderResponse renderResponse)
095                    throws IOException, PortletException {
096    
097                    PortletPreferences portletPreferences = renderRequest.getPreferences();
098    
099                    if (portletPreferences == null) {
100                            super.doEdit(renderRequest, renderResponse);
101                    }
102                    else {
103                            include(editDefaultsTemplate, renderRequest, renderResponse);
104                    }
105            }
106    
107            @Override
108            public void doEditGuest(
109                            RenderRequest renderRequest, RenderResponse renderResponse)
110                    throws IOException, PortletException {
111    
112                    PortletPreferences portletPreferences = renderRequest.getPreferences();
113    
114                    if (portletPreferences == null) {
115                            super.doEdit(renderRequest, renderResponse);
116                    }
117                    else {
118                            include(editGuestTemplate, renderRequest, renderResponse);
119                    }
120            }
121    
122            @Override
123            public void doHelp(
124                            RenderRequest renderRequest, RenderResponse renderResponse)
125                    throws IOException, PortletException {
126    
127                    include(helpTemplate, renderRequest, renderResponse);
128            }
129    
130            @Override
131            public void doPreview(
132                            RenderRequest renderRequest, RenderResponse renderResponse)
133                    throws IOException, PortletException {
134    
135                    include(previewTemplate, renderRequest, renderResponse);
136            }
137    
138            @Override
139            public void doPrint(
140                            RenderRequest renderRequest, RenderResponse renderResponse)
141                    throws IOException, PortletException {
142    
143                    include(printTemplate, renderRequest, renderResponse);
144            }
145    
146            @Override
147            public void doView(
148                            RenderRequest renderRequest, RenderResponse renderResponse)
149                    throws IOException, PortletException {
150    
151                    include(viewTemplate, renderRequest, renderResponse);
152            }
153    
154            @Override
155            public void init() throws PortletException {
156                    super.init();
157    
158                    templatePath = _getInitParameter("template-path");
159    
160                    if (Validator.isNull(templatePath)) {
161                            templatePath = StringPool.SLASH;
162                    }
163                    else if (templatePath.contains(StringPool.BACK_SLASH) ||
164                                     templatePath.contains(StringPool.DOUBLE_SLASH) ||
165                                     templatePath.contains(StringPool.PERIOD) ||
166                                     templatePath.contains(StringPool.SPACE)) {
167    
168                            throw new PortletException(
169                                    "template-path " + templatePath + " has invalid characters");
170                    }
171                    else if (!templatePath.startsWith(StringPool.SLASH) ||
172                                     !templatePath.endsWith(StringPool.SLASH)) {
173    
174                            throw new PortletException(
175                                    "template-path " + templatePath +
176                                            " must start and end with a /");
177                    }
178    
179                    aboutTemplate = _getInitParameter("about-template");
180                    configTemplate = _getInitParameter("config-template");
181                    editTemplate = _getInitParameter("edit-template");
182                    editDefaultsTemplate = _getInitParameter("edit-defaults-template");
183                    editGuestTemplate = _getInitParameter("edit-guest-template");
184                    helpTemplate = _getInitParameter("help-template");
185                    previewTemplate = _getInitParameter("preview-template");
186                    printTemplate = _getInitParameter("print-template");
187                    viewTemplate = _getInitParameter("view-template");
188    
189                    clearRequestParameters = GetterUtil.getBoolean(
190                            getInitParameter("clear-request-parameters"));
191                    copyRequestParameters = GetterUtil.getBoolean(
192                            getInitParameter("copy-request-parameters"));
193    
194                    String packagePrefix = getInitParameter(
195                            ActionCommandCache.ACTION_PACKAGE_NAME);
196    
197                    _actionCommandCache = new ActionCommandCache(
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            @Override
212            public void processAction(
213                            ActionRequest actionRequest, ActionResponse actionResponse)
214                    throws IOException, PortletException {
215    
216                    super.processAction(actionRequest, actionResponse);
217    
218                    if (copyRequestParameters) {
219                            PortalUtil.copyRequestParameters(actionRequest, actionResponse);
220                    }
221            }
222    
223            @Override
224            public void serveResource(
225                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
226                    throws IOException, PortletException {
227    
228                    String path = getPath(resourceRequest);
229    
230                    if (path != null) {
231                            include(
232                                    path, resourceRequest, resourceResponse,
233                                    PortletRequest.RESOURCE_PHASE);
234                    }
235                    else {
236                            super.serveResource(resourceRequest, resourceResponse);
237                    }
238            }
239    
240            @Override
241            protected boolean callActionMethod(
242                            ActionRequest actionRequest, ActionResponse actionResponse)
243                    throws PortletException {
244    
245                    try {
246                            checkPermissions(actionRequest);
247                    }
248                    catch (Exception e) {
249                            throw new PortletException(e);
250                    }
251    
252                    String actionName = ParamUtil.getString(
253                            actionRequest, ActionRequest.ACTION_NAME);
254    
255                    if (!actionName.contains(StringPool.COMMA)) {
256                            ActionCommand actionCommand = _actionCommandCache.getActionCommand(
257                                    actionName);
258    
259                            if (actionCommand != ActionCommandCache.EMPTY) {
260                                    return actionCommand.processCommand(
261                                            actionRequest, actionResponse);
262                            }
263                    }
264                    else {
265                            List<ActionCommand> actionCommands =
266                                    _actionCommandCache.getActionCommandChain(actionName);
267    
268                            if (!actionCommands.isEmpty()) {
269                                    for (ActionCommand actionCommand : actionCommands) {
270                                            if (!actionCommand.processCommand(
271                                                            actionRequest, actionResponse)) {
272    
273                                                    return false;
274                                            }
275                                    }
276    
277                                    return true;
278                            }
279                    }
280    
281                    return super.callActionMethod(actionRequest, actionResponse);
282            }
283    
284            @Override
285            protected boolean callResourceMethod(
286                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
287                    throws PortletException {
288    
289                    try {
290                            checkPermissions(resourceRequest);
291                    }
292                    catch (Exception e) {
293                            throw new PortletException(e);
294                    }
295    
296                    String actionName = ParamUtil.getString(
297                            resourceRequest, ActionRequest.ACTION_NAME);
298    
299                    if (!actionName.contains(StringPool.COMMA)) {
300                            ActionCommand actionCommand = _actionCommandCache.getActionCommand(
301                                    actionName);
302    
303                            if (actionCommand != ActionCommandCache.EMPTY) {
304                                    return actionCommand.processCommand(
305                                            resourceRequest, resourceResponse);
306                            }
307                    }
308                    else {
309                            List<ActionCommand> actionCommands =
310                                    _actionCommandCache.getActionCommandChain(actionName);
311    
312                            if (!actionCommands.isEmpty()) {
313                                    for (ActionCommand actionCommand : actionCommands) {
314                                            if (!actionCommand.processCommand(
315                                                            resourceRequest, resourceResponse)) {
316    
317                                                    return false;
318                                            }
319                                    }
320    
321                                    return true;
322                            }
323                    }
324    
325                    return super.callResourceMethod(resourceRequest, resourceResponse);
326            }
327    
328            protected void checkPath(String path) throws PortletException {
329                    if (Validator.isNotNull(path) &&
330                            (!path.startsWith(templatePath) ||
331                             !PortalUtil.isValidResourceId(path) ||
332                             !Validator.isFilePath(path, false))) {
333    
334                            throw new PortletException(
335                                    "Path " + path + " is not accessible by this portlet");
336                    }
337            }
338    
339            protected void checkPermissions(PortletRequest portletRequest)
340                    throws Exception {
341            }
342    
343            @Override
344            protected void doDispatch(
345                            RenderRequest renderRequest, RenderResponse renderResponse)
346                    throws IOException, PortletException {
347    
348                    String path = getPath(renderRequest);
349    
350                    if (path != null) {
351                            if (!isProcessRenderRequest(renderRequest)) {
352                                    renderRequest.setAttribute(
353                                            WebKeys.PORTLET_DECORATE, Boolean.FALSE);
354    
355                                    return;
356                            }
357    
358                            WindowState windowState = renderRequest.getWindowState();
359    
360                            if (windowState.equals(WindowState.MINIMIZED)) {
361                                    return;
362                            }
363    
364                            include(path, renderRequest, renderResponse);
365                    }
366                    else {
367                            super.doDispatch(renderRequest, renderResponse);
368                    }
369            }
370    
371            protected String getPath(PortletRequest portletRequest) {
372                    String mvcPath = portletRequest.getParameter("mvcPath");
373    
374                    // Check deprecated parameter
375    
376                    if (mvcPath == null) {
377                            mvcPath = portletRequest.getParameter("jspPage");
378                    }
379    
380                    return mvcPath;
381            }
382    
383            protected void include(
384                            String path, ActionRequest actionRequest,
385                            ActionResponse actionResponse)
386                    throws IOException, PortletException {
387    
388                    include(
389                            path, actionRequest, actionResponse, PortletRequest.ACTION_PHASE);
390            }
391    
392            protected void include(
393                            String path, EventRequest eventRequest, EventResponse eventResponse)
394                    throws IOException, PortletException {
395    
396                    include(path, eventRequest, eventResponse, PortletRequest.EVENT_PHASE);
397            }
398    
399            protected void include(
400                            String path, PortletRequest portletRequest,
401                            PortletResponse portletResponse, String lifecycle)
402                    throws IOException, PortletException {
403    
404                    PortletContext portletContext = getPortletContext();
405    
406                    PortletRequestDispatcher portletRequestDispatcher =
407                            portletContext.getRequestDispatcher(path);
408    
409                    if (portletRequestDispatcher == null) {
410                            _log.error(path + " is not a valid include");
411                    }
412                    else {
413                            checkPath(path);
414    
415                            portletRequestDispatcher.include(portletRequest, portletResponse);
416                    }
417    
418                    if (clearRequestParameters) {
419                            if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
420                                    portletResponse.setProperty(
421                                            "clear-request-parameters", Boolean.TRUE.toString());
422                            }
423                    }
424            }
425    
426            protected void include(
427                            String path, RenderRequest renderRequest,
428                            RenderResponse renderResponse)
429                    throws IOException, PortletException {
430    
431                    include(
432                            path, renderRequest, renderResponse, PortletRequest.RENDER_PHASE);
433            }
434    
435            protected void include(
436                            String path, ResourceRequest resourceRequest,
437                            ResourceResponse resourceResponse)
438                    throws IOException, PortletException {
439    
440                    include(
441                            path, resourceRequest, resourceResponse,
442                            PortletRequest.RESOURCE_PHASE);
443            }
444    
445            protected String aboutTemplate;
446            protected boolean clearRequestParameters;
447            protected String configTemplate;
448            protected boolean copyRequestParameters;
449            protected String editDefaultsTemplate;
450            protected String editGuestTemplate;
451            protected String editTemplate;
452            protected String helpTemplate;
453            protected String previewTemplate;
454            protected String printTemplate;
455            protected String templatePath;
456            protected String viewTemplate;
457    
458            private String _getInitParameter(String name) {
459                    String value = getInitParameter(name);
460    
461                    if (value != null) {
462                            return value;
463                    }
464    
465                    // Check deprecated parameter
466    
467                    if (name.equals("template-path")) {
468                            return getInitParameter("jsp-path");
469                    }
470                    else if (name.endsWith("-template")) {
471                            name = name.substring(0, name.length() - 9) + "-jsp";
472    
473                            return getInitParameter(name);
474                    }
475    
476                    return null;
477            }
478    
479            private static final Log _log = LogFactoryUtil.getLog(MVCPortlet.class);
480    
481            private ActionCommandCache _actionCommandCache;
482    
483    }