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