001    /**
002     * Copyright (c) 2000-2011 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.PortalClassInvoker;
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.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     */
051    public class MVCPortlet extends LiferayPortlet {
052    
053            @Override
054            public void doAbout(
055                            RenderRequest renderRequest, RenderResponse renderResponse)
056                    throws IOException, PortletException {
057    
058                    include(aboutJSP, renderRequest, renderResponse);
059            }
060    
061            @Override
062            public void doConfig(
063                            RenderRequest renderRequest, RenderResponse renderResponse)
064                    throws IOException, PortletException {
065    
066                    include(configJSP, renderRequest, renderResponse);
067            }
068    
069            @Override
070            public void doEdit(
071                            RenderRequest renderRequest, RenderResponse renderResponse)
072                    throws IOException, PortletException {
073    
074                    if (renderRequest.getPreferences() == null) {
075                            super.doEdit(renderRequest, renderResponse);
076                    }
077                    else {
078                            include(editJSP, renderRequest, renderResponse);
079                    }
080            }
081    
082            @Override
083            public void doEditDefaults(
084                            RenderRequest renderRequest, RenderResponse renderResponse)
085                    throws IOException, PortletException {
086    
087                    if (renderRequest.getPreferences() == null) {
088                            super.doEdit(renderRequest, renderResponse);
089                    }
090                    else {
091                            include(editDefaultsJSP, renderRequest, renderResponse);
092                    }
093            }
094    
095            @Override
096            public void doEditGuest(
097                            RenderRequest renderRequest, RenderResponse renderResponse)
098                    throws IOException, PortletException {
099    
100                    if (renderRequest.getPreferences() == null) {
101                            super.doEdit(renderRequest, renderResponse);
102                    }
103                    else {
104                            include(editGuestJSP, renderRequest, renderResponse);
105                    }
106            }
107    
108            @Override
109            public void doHelp(
110                            RenderRequest renderRequest, RenderResponse renderResponse)
111                    throws IOException, PortletException {
112    
113                    include(helpJSP, renderRequest, renderResponse);
114            }
115    
116            @Override
117            public void doPreview(
118                            RenderRequest renderRequest, RenderResponse renderResponse)
119                    throws IOException, PortletException {
120    
121                    include(previewJSP, renderRequest, renderResponse);
122            }
123    
124            @Override
125            public void doPrint(
126                            RenderRequest renderRequest, RenderResponse renderResponse)
127                    throws IOException, PortletException {
128    
129                    include(printJSP, renderRequest, renderResponse);
130            }
131    
132            @Override
133            public void doView(
134                            RenderRequest renderRequest, RenderResponse renderResponse)
135                    throws IOException, PortletException {
136    
137                    include(viewJSP, renderRequest, renderResponse);
138            }
139    
140            @Override
141            public void init() throws PortletException {
142                    super.init();
143    
144                    jspPath = getInitParameter("jsp-path");
145    
146                    if (Validator.isNull(jspPath)) {
147                            jspPath = StringPool.SLASH;
148                    }
149                    else if (jspPath.contains(StringPool.BACK_SLASH) ||
150                                     jspPath.contains(StringPool.DOUBLE_SLASH) ||
151                                     jspPath.contains(StringPool.PERIOD) ||
152                                     jspPath.contains(StringPool.SPACE)) {
153    
154                            throw new PortletException(
155                                    "jsp-path " + jspPath + " has invalid characters");
156                    }
157                    else if (!jspPath.startsWith(StringPool.SLASH) ||
158                                     !jspPath.endsWith(StringPool.SLASH)) {
159    
160                            throw new PortletException(
161                                    "jsp-path " + jspPath + " must start and end with a /");
162                    }
163    
164                    aboutJSP = getInitParameter("about-jsp");
165                    configJSP = getInitParameter("config-jsp");
166                    editJSP = getInitParameter("edit-jsp");
167                    editDefaultsJSP = getInitParameter("edit-defaults-jsp");
168                    editGuestJSP = getInitParameter("edit-guest-jsp");
169                    helpJSP = getInitParameter("help-jsp");
170                    previewJSP = getInitParameter("preview-jsp");
171                    printJSP = getInitParameter("print-jsp");
172                    viewJSP = getInitParameter("view-jsp");
173    
174                    clearRequestParameters = GetterUtil.getBoolean(
175                            getInitParameter("clear-request-parameters"));
176                    copyRequestParameters = GetterUtil.getBoolean(
177                            getInitParameter("copy-request-parameters"));
178    
179                    String packagePrefix = getInitParameter(
180                            ActionCommandCache.ACTION_PACKAGE_NAME);
181    
182                    if (Validator.isNotNull(packagePrefix)) {
183                            _actionCommandCache = new ActionCommandCache(packagePrefix);
184                    }
185            }
186    
187            public void invokeTaglibDiscussion(
188                            ActionRequest actionRequest, ActionResponse actionResponse)
189                    throws Exception {
190    
191                    PortletConfig portletConfig = getPortletConfig();
192    
193                    PortalClassInvoker.invoke(
194                            true,
195                            "com.liferay.portlet.messageboards.action.EditDiscussionAction",
196                            "processAction",
197                            new String[] {
198                                    "org.apache.struts.action.ActionMapping",
199                                    "org.apache.struts.action.ActionForm",
200                                    PortletConfig.class.getName(), ActionRequest.class.getName(),
201                                    ActionResponse.class.getName()
202                            },
203                            null, null, portletConfig, actionRequest, actionResponse);
204            }
205    
206            @Override
207            public void processAction(
208                            ActionRequest actionRequest, ActionResponse actionResponse)
209                    throws IOException, PortletException {
210    
211                    super.processAction(actionRequest, actionResponse);
212    
213                    if (copyRequestParameters) {
214                            PortalUtil.copyRequestParameters(actionRequest, actionResponse);
215                    }
216            }
217    
218            @Override
219            public void serveResource(
220                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
221                    throws IOException, PortletException {
222    
223                    String jspPage = resourceRequest.getParameter("jspPage");
224    
225                    if (jspPage != null) {
226                            include(
227                                    jspPage, resourceRequest, resourceResponse,
228                                    PortletRequest.RESOURCE_PHASE);
229                    }
230                    else {
231                            super.serveResource(resourceRequest, resourceResponse);
232                    }
233            }
234    
235            @Override
236            protected boolean callActionMethod(
237                            ActionRequest request, ActionResponse response)
238                    throws PortletException {
239    
240                    if (_actionCommandCache == null) {
241                            return super.callActionMethod(request, response);
242                    }
243    
244                    String actionName = ParamUtil.getString(
245                            request, ActionRequest.ACTION_NAME);
246    
247                    if (!actionName.contains(StringPool.COMMA)) {
248                            ActionCommand actionCommand = _actionCommandCache.getActionCommand(
249                                    actionName);
250    
251                            if (actionCommand != ActionCommandCache.EMPTY) {
252                                    return actionCommand.processCommand(request, response);
253                            }
254                    }
255                    else {
256                            List<ActionCommand> actionCommands =
257                                    _actionCommandCache.getActionCommandChain(actionName);
258    
259                            if (actionCommands.isEmpty()) {
260                                    return false;
261                            }
262    
263                            for (ActionCommand actionCommand : actionCommands) {
264                                    if (!actionCommand.processCommand(request, response)) {
265                                            return false;
266                                    }
267                            }
268    
269                            return true;
270                    }
271    
272                    return false;
273            }
274    
275            protected void checkJSPPath(String path) throws PortletException {
276                    if (!path.startsWith(jspPath) ||
277                            path.contains(StringPool.DOUBLE_PERIOD) ||
278                            !PortalUtil.isValidResourceId(path)) {
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 jspPage = renderRequest.getParameter("jspPage");
291    
292                    if (jspPage != 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(jspPage, renderRequest, renderResponse);
307                    }
308                    else {
309                            super.doDispatch(renderRequest, renderResponse);
310                    }
311            }
312    
313            protected void include(
314                            String path, ActionRequest actionRequest,
315                            ActionResponse actionResponse)
316                    throws IOException, PortletException {
317    
318                    include(
319                            path, actionRequest, actionResponse, PortletRequest.ACTION_PHASE);
320            }
321    
322            protected void include(
323                            String path, EventRequest eventRequest, EventResponse eventResponse)
324                    throws IOException, PortletException {
325    
326                    include(path, eventRequest, eventResponse, PortletRequest.EVENT_PHASE);
327            }
328    
329            protected void include(
330                            String path, PortletRequest portletRequest,
331                            PortletResponse portletResponse, String lifecycle)
332                    throws IOException, PortletException {
333    
334                    PortletContext portletContext = getPortletContext();
335    
336                    PortletRequestDispatcher portletRequestDispatcher =
337                            portletContext.getRequestDispatcher(path);
338    
339                    if (portletRequestDispatcher == null) {
340                            _log.error(path + " is not a valid include");
341                    }
342                    else {
343                            checkJSPPath(path);
344    
345                            portletRequestDispatcher.include(portletRequest, portletResponse);
346                    }
347    
348                    if (clearRequestParameters) {
349                            if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
350                                    portletResponse.setProperty("clear-request-parameters", "true");
351                            }
352                    }
353            }
354    
355            protected void include(
356                            String path, RenderRequest renderRequest,
357                            RenderResponse renderResponse)
358                    throws IOException, PortletException {
359    
360                    include(
361                            path, renderRequest, renderResponse, PortletRequest.RENDER_PHASE);
362            }
363    
364            protected void include(
365                            String path, ResourceRequest resourceRequest,
366                            ResourceResponse resourceResponse)
367                    throws IOException, PortletException {
368    
369                    include(
370                            path, resourceRequest, resourceResponse,
371                            PortletRequest.RESOURCE_PHASE);
372            }
373    
374            private static Log _log = LogFactoryUtil.getLog(MVCPortlet.class);
375    
376            protected ActionCommandCache _actionCommandCache;
377    
378            protected String aboutJSP;
379            protected boolean clearRequestParameters;
380            protected String configJSP;
381            protected boolean copyRequestParameters;
382            protected String editDefaultsJSP;
383            protected String editGuestJSP;
384            protected String editJSP;
385            protected String helpJSP;
386            protected String jspPath;
387            protected String previewJSP;
388            protected String printJSP;
389            protected String viewJSP;
390    
391    }