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