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