1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.util.bridges.scripting;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.scripting.ScriptingException;
20  import com.liferay.portal.kernel.scripting.ScriptingUtil;
21  import com.liferay.portal.kernel.servlet.SessionErrors;
22  import com.liferay.portal.kernel.util.ContentTypes;
23  import com.liferay.portal.kernel.util.FileUtil;
24  import com.liferay.portal.kernel.util.HtmlUtil;
25  import com.liferay.portal.kernel.util.StringBundler;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.StringUtil;
28  import com.liferay.portal.kernel.util.WebKeys;
29  import com.liferay.portal.security.permission.ActionKeys;
30  import com.liferay.portal.security.permission.PermissionChecker;
31  import com.liferay.portal.service.permission.PortalPermissionUtil;
32  import com.liferay.portal.theme.ThemeDisplay;
33  import com.liferay.util.servlet.PortletResponseUtil;
34  
35  import java.io.IOException;
36  import java.io.InputStream;
37  
38  import java.util.Map;
39  
40  import javax.portlet.ActionRequest;
41  import javax.portlet.ActionResponse;
42  import javax.portlet.GenericPortlet;
43  import javax.portlet.PortletConfig;
44  import javax.portlet.PortletContext;
45  import javax.portlet.PortletException;
46  import javax.portlet.PortletRequest;
47  import javax.portlet.PortletResponse;
48  import javax.portlet.RenderRequest;
49  import javax.portlet.RenderResponse;
50  import javax.portlet.ResourceRequest;
51  import javax.portlet.ResourceResponse;
52  
53  /**
54   * <a href="ScriptingPortlet.java.html"><b><i>View Source</i></b></a>
55   *
56   * @author Jorge Ferrer
57   * @author Brian Wing Shun Chan
58   * @author Alberto Montero
59   */
60  public class ScriptingPortlet extends GenericPortlet {
61  
62      public void init() {
63          actionFile = getInitParameter("action-file");
64          editFile = getInitParameter("edit-file");
65          helpFile = getInitParameter("help-file");
66          resourceFile = getInitParameter("resource-file");
67          viewFile = getInitParameter("view-file");
68  
69          language = getInitParameter("scripting-language");
70          globalFiles = StringUtil.split(getInitParameter("global-files"));
71      }
72  
73      public void doDispatch(
74              RenderRequest renderRequest, RenderResponse renderResponse)
75          throws IOException, PortletException {
76  
77          String fileName = getFileName(renderRequest);
78  
79          if (fileName != null) {
80              include(fileName, renderRequest, renderResponse);
81          }
82          else {
83              super.doDispatch(renderRequest, renderResponse);
84          }
85      }
86  
87      public void doEdit(
88              RenderRequest renderRequest, RenderResponse renderResponse)
89          throws IOException, PortletException {
90  
91          if (renderRequest.getPreferences() == null) {
92              super.doEdit(renderRequest, renderResponse);
93          }
94          else {
95              include(editFile, renderRequest, renderResponse);
96          }
97      }
98  
99      public void doHelp(
100             RenderRequest renderRequest, RenderResponse renderResponse)
101         throws IOException {
102 
103         include(helpFile, renderRequest, renderResponse);
104     }
105 
106     public void doView(
107             RenderRequest renderRequest, RenderResponse renderResponse)
108         throws IOException {
109 
110         include(viewFile, renderRequest, renderResponse);
111     }
112 
113     public void processAction(
114             ActionRequest actionRequest, ActionResponse actionResponse)
115         throws IOException {
116 
117         include(actionFile, actionRequest, actionResponse);
118     }
119 
120     public void render(
121             RenderRequest renderRequest, RenderResponse renderResponse)
122         throws IOException, PortletException {
123 
124         try {
125             doRender(renderRequest, renderResponse);
126         }
127         catch (IOException ioe) {
128             throw ioe;
129         }
130         catch (PortletException pe) {
131             throw pe;
132         }
133         catch (Exception e) {
134             throw new PortletException(e);
135         }
136     }
137 
138     public void serveResource(
139             ResourceRequest resourceRequest, ResourceResponse resourceResponse)
140         throws IOException {
141 
142         include(resourceFile, resourceRequest, resourceResponse);
143     }
144 
145     protected void declareBeans(
146             InputStream is, PortletRequest portletRequest,
147             PortletResponse portletResponse)
148         throws IOException, ScriptingException {
149 
150         String script = new String(FileUtil.getBytes(is));
151 
152         declareBeans(script, portletRequest, portletResponse);
153     }
154 
155     protected void declareBeans(
156             String script, PortletRequest portletRequest,
157             PortletResponse portletResponse)
158         throws IOException, ScriptingException {
159 
160         script = getGlobalScript() + script;
161 
162         PortletConfig portletConfig = getPortletConfig();
163         PortletContext portletContext = getPortletContext();
164 
165         Map<String, Object> portletObjects = ScriptingUtil.getPortletObjects(
166             portletConfig, portletContext, portletRequest, portletResponse);
167 
168         ScriptingUtil.exec(null, portletObjects, language, script);
169     }
170 
171     protected void doRender(
172             RenderRequest renderRequest, RenderResponse renderResponse)
173         throws Exception {
174 
175         Object error = SessionErrors.get(renderRequest, _ERROR);
176 
177         if (error != null) {
178             Exception e = (Exception)error;
179 
180             writeErrorMessage(renderRequest, renderResponse, e.getMessage());
181 
182             return;
183         }
184 
185         super.render(renderRequest, renderResponse);
186 
187         error = SessionErrors.get(renderRequest, _ERROR);
188 
189         if (error != null) {
190             Exception e = (Exception)error;
191 
192             writeErrorMessage(renderRequest, renderResponse, e.getMessage());
193         }
194     }
195 
196     protected String getFileName(RenderRequest renderRequest) {
197         return renderRequest.getParameter("file");
198     }
199 
200     protected String getGlobalScript() throws IOException {
201         if (globalScript != null) {
202             return globalScript;
203         }
204 
205         if (globalFiles.length == 0) {
206             globalScript = StringPool.BLANK;
207 
208             return globalScript;
209         }
210 
211         StringBundler sb = new StringBundler();
212 
213         for (String globalFile : globalFiles) {
214             InputStream is = getPortletContext().getResourceAsStream(
215                 globalFile);
216 
217             if (is == null) {
218                 if (_log.isWarnEnabled()) {
219                     _log.warn("Global file " + globalFile + " does not exist");
220                 }
221             }
222 
223             try {
224                 if (is != null) {
225                     String script = new String(FileUtil.getBytes(is));
226 
227                     sb.append(script);
228                     sb.append(StringPool.NEW_LINE);
229                 }
230             }
231             finally {
232                 is.close();
233             }
234         }
235 
236         globalScript = sb.toString();
237 
238         return globalScript;
239     }
240 
241     protected void include(
242             String path, PortletRequest portletRequest,
243             PortletResponse portletResponse)
244         throws IOException {
245 
246         InputStream is = getPortletContext().getResourceAsStream(path);
247 
248         if (is == null) {
249             _log.error(path + " is not a valid " + language + " file");
250 
251             return;
252         }
253 
254         try {
255             declareBeans(is, portletRequest, portletResponse);
256         }
257         catch (ScriptingException se) {
258             SessionErrors.add(portletRequest, _ERROR, se);
259         }
260         finally {
261             is.close();
262         }
263     }
264 
265     protected void writeErrorMessage(
266             RenderRequest renderRequest, RenderResponse renderResponse,
267             String errorMessage)
268         throws Exception {
269 
270         ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
271             WebKeys.THEME_DISPLAY);
272 
273         PermissionChecker permissionChecker =
274             themeDisplay.getPermissionChecker();
275 
276         StringBundler sb = new StringBundler(6);
277 
278         sb.append("<div class=\"portlet-msg-error\">");
279         sb.append(themeDisplay.translate("an-unexpected-error-occurred"));
280         sb.append("</div>");
281 
282         if (PortalPermissionUtil.contains(
283                 permissionChecker, ActionKeys.CONFIGURATION)) {
284 
285             sb.append("<pre>");
286             sb.append(HtmlUtil.escape(errorMessage));
287             sb.append("</pre>");
288         }
289 
290         renderResponse.setContentType(ContentTypes.TEXT_HTML);
291 
292         PortletResponseUtil.write(renderResponse, sb.toString());
293     }
294 
295     private static final String _ERROR = ScriptingPortlet.class + ".ERROR";
296 
297     private static Log _log = LogFactoryUtil.getLog(ScriptingPortlet.class);
298 
299     protected String actionFile;
300     protected String editFile;
301     protected String helpFile;
302     protected String[] globalFiles;
303     protected String globalScript;
304     protected String resourceFile;
305     protected String language;
306     protected String viewFile;
307 
308 }