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.scripting;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.scripting.ScriptingException;
020    import com.liferay.portal.kernel.scripting.ScriptingUtil;
021    import com.liferay.portal.kernel.servlet.SessionErrors;
022    import com.liferay.portal.kernel.util.ContentTypes;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.HtmlUtil;
025    import com.liferay.portal.kernel.util.StringBundler;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.util.WebKeys;
029    import com.liferay.portal.security.permission.ActionKeys;
030    import com.liferay.portal.security.permission.PermissionChecker;
031    import com.liferay.portal.service.permission.PortalPermissionUtil;
032    import com.liferay.portal.theme.ThemeDisplay;
033    import com.liferay.util.servlet.PortletResponseUtil;
034    
035    import java.io.IOException;
036    import java.io.InputStream;
037    
038    import java.util.Map;
039    
040    import javax.portlet.ActionRequest;
041    import javax.portlet.ActionResponse;
042    import javax.portlet.GenericPortlet;
043    import javax.portlet.PortletConfig;
044    import javax.portlet.PortletContext;
045    import javax.portlet.PortletException;
046    import javax.portlet.PortletRequest;
047    import javax.portlet.PortletResponse;
048    import javax.portlet.RenderRequest;
049    import javax.portlet.RenderResponse;
050    import javax.portlet.ResourceRequest;
051    import javax.portlet.ResourceResponse;
052    
053    /**
054     * @author Jorge Ferrer
055     * @author Brian Wing Shun Chan
056     * @author Alberto Montero
057     */
058    public class ScriptingPortlet extends GenericPortlet {
059    
060            public void init() {
061                    actionFile = getInitParameter("action-file");
062                    editFile = getInitParameter("edit-file");
063                    helpFile = getInitParameter("help-file");
064                    resourceFile = getInitParameter("resource-file");
065                    viewFile = getInitParameter("view-file");
066    
067                    language = getInitParameter("scripting-language");
068                    globalFiles = StringUtil.split(getInitParameter("global-files"));
069            }
070    
071            public void doDispatch(
072                            RenderRequest renderRequest, RenderResponse renderResponse)
073                    throws IOException, PortletException {
074    
075                    String fileName = getFileName(renderRequest);
076    
077                    if (fileName != null) {
078                            include(fileName, renderRequest, renderResponse);
079                    }
080                    else {
081                            super.doDispatch(renderRequest, renderResponse);
082                    }
083            }
084    
085            public void doEdit(
086                            RenderRequest renderRequest, RenderResponse renderResponse)
087                    throws IOException, PortletException {
088    
089                    if (renderRequest.getPreferences() == null) {
090                            super.doEdit(renderRequest, renderResponse);
091                    }
092                    else {
093                            include(editFile, renderRequest, renderResponse);
094                    }
095            }
096    
097            public void doHelp(
098                            RenderRequest renderRequest, RenderResponse renderResponse)
099                    throws IOException {
100    
101                    include(helpFile, renderRequest, renderResponse);
102            }
103    
104            public void doView(
105                            RenderRequest renderRequest, RenderResponse renderResponse)
106                    throws IOException {
107    
108                    include(viewFile, renderRequest, renderResponse);
109            }
110    
111            public void processAction(
112                            ActionRequest actionRequest, ActionResponse actionResponse)
113                    throws IOException {
114    
115                    include(actionFile, actionRequest, actionResponse);
116            }
117    
118            public void render(
119                            RenderRequest renderRequest, RenderResponse renderResponse)
120                    throws IOException, PortletException {
121    
122                    try {
123                            doRender(renderRequest, renderResponse);
124                    }
125                    catch (IOException ioe) {
126                            throw ioe;
127                    }
128                    catch (PortletException pe) {
129                            throw pe;
130                    }
131                    catch (Exception e) {
132                            throw new PortletException(e);
133                    }
134            }
135    
136            public void serveResource(
137                            ResourceRequest resourceRequest, ResourceResponse resourceResponse)
138                    throws IOException {
139    
140                    include(resourceFile, resourceRequest, resourceResponse);
141            }
142    
143            protected void declareBeans(
144                            InputStream is, PortletRequest portletRequest,
145                            PortletResponse portletResponse)
146                    throws IOException, ScriptingException {
147    
148                    String script = new String(FileUtil.getBytes(is));
149    
150                    declareBeans(script, portletRequest, portletResponse);
151            }
152    
153            protected void declareBeans(
154                            String script, PortletRequest portletRequest,
155                            PortletResponse portletResponse)
156                    throws IOException, ScriptingException {
157    
158                    script = getGlobalScript() + script;
159    
160                    PortletConfig portletConfig = getPortletConfig();
161                    PortletContext portletContext = getPortletContext();
162    
163                    Map<String, Object> portletObjects = ScriptingUtil.getPortletObjects(
164                            portletConfig, portletContext, portletRequest, portletResponse);
165    
166                    ScriptingUtil.exec(null, portletObjects, language, script);
167            }
168    
169            protected void doRender(
170                            RenderRequest renderRequest, RenderResponse renderResponse)
171                    throws Exception {
172    
173                    Object error = SessionErrors.get(renderRequest, _ERROR);
174    
175                    if (error != null) {
176                            Exception e = (Exception)error;
177    
178                            writeErrorMessage(renderRequest, renderResponse, e.getMessage());
179    
180                            return;
181                    }
182    
183                    super.render(renderRequest, renderResponse);
184    
185                    error = SessionErrors.get(renderRequest, _ERROR);
186    
187                    if (error != null) {
188                            Exception e = (Exception)error;
189    
190                            writeErrorMessage(renderRequest, renderResponse, e.getMessage());
191                    }
192            }
193    
194            protected String getFileName(RenderRequest renderRequest) {
195                    return renderRequest.getParameter("file");
196            }
197    
198            protected String getGlobalScript() throws IOException {
199                    if (globalScript != null) {
200                            return globalScript;
201                    }
202    
203                    if (globalFiles.length == 0) {
204                            globalScript = StringPool.BLANK;
205    
206                            return globalScript;
207                    }
208    
209                    StringBundler sb = new StringBundler();
210    
211                    for (String globalFile : globalFiles) {
212                            InputStream is = getPortletContext().getResourceAsStream(
213                                    globalFile);
214    
215                            if (is == null) {
216                                    if (_log.isWarnEnabled()) {
217                                            _log.warn("Global file " + globalFile + " does not exist");
218                                    }
219                            }
220    
221                            try {
222                                    if (is != null) {
223                                            String script = new String(FileUtil.getBytes(is));
224    
225                                            sb.append(script);
226                                            sb.append(StringPool.NEW_LINE);
227                                    }
228                            }
229                            finally {
230                                    is.close();
231                            }
232                    }
233    
234                    globalScript = sb.toString();
235    
236                    return globalScript;
237            }
238    
239            protected void include(
240                            String path, PortletRequest portletRequest,
241                            PortletResponse portletResponse)
242                    throws IOException {
243    
244                    InputStream is = getPortletContext().getResourceAsStream(path);
245    
246                    if (is == null) {
247                            _log.error(path + " is not a valid " + language + " file");
248    
249                            return;
250                    }
251    
252                    try {
253                            declareBeans(is, portletRequest, portletResponse);
254                    }
255                    catch (ScriptingException se) {
256                            SessionErrors.add(portletRequest, _ERROR, se);
257                    }
258                    finally {
259                            is.close();
260                    }
261            }
262    
263            protected void writeErrorMessage(
264                            RenderRequest renderRequest, RenderResponse renderResponse,
265                            String errorMessage)
266                    throws Exception {
267    
268                    ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
269                            WebKeys.THEME_DISPLAY);
270    
271                    PermissionChecker permissionChecker =
272                            themeDisplay.getPermissionChecker();
273    
274                    StringBundler sb = new StringBundler(6);
275    
276                    sb.append("<div class=\"portlet-msg-error\">");
277                    sb.append(themeDisplay.translate("an-unexpected-error-occurred"));
278                    sb.append("</div>");
279    
280                    if (PortalPermissionUtil.contains(
281                                    permissionChecker, ActionKeys.CONFIGURATION)) {
282    
283                            sb.append("<pre>");
284                            sb.append(HtmlUtil.escape(errorMessage));
285                            sb.append("</pre>");
286                    }
287    
288                    renderResponse.setContentType(ContentTypes.TEXT_HTML);
289    
290                    PortletResponseUtil.write(renderResponse, sb.toString());
291            }
292    
293            private static final String _ERROR = ScriptingPortlet.class + ".ERROR";
294    
295            private static Log _log = LogFactoryUtil.getLog(ScriptingPortlet.class);
296    
297            protected String actionFile;
298            protected String editFile;
299            protected String helpFile;
300            protected String[] globalFiles;
301            protected String globalScript;
302            protected String resourceFile;
303            protected String language;
304            protected String viewFile;
305    
306    }