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 + " must start and end with a /");
128 }
129
130 actionFile = getInitParameter("action-file");
131 editFile = getInitParameter("edit-file");
132 helpFile = getInitParameter("help-file");
133 resourceFile = getInitParameter("resource-file");
134 viewFile = getInitParameter("view-file");
135
136 language = getInitParameter("scripting-language");
137 globalFiles = StringUtil.split(getInitParameter("global-files"));
138 }
139
140 @Override
141 public void processAction(
142 ActionRequest actionRequest, ActionResponse actionResponse)
143 throws IOException, PortletException {
144
145 include(actionFile, actionRequest, actionResponse);
146 }
147
148 @Override
149 public void render(
150 RenderRequest renderRequest, RenderResponse renderResponse)
151 throws IOException, PortletException {
152
153 try {
154 doRender(renderRequest, renderResponse);
155 }
156 catch (IOException ioe) {
157 throw ioe;
158 }
159 catch (PortletException pe) {
160 throw pe;
161 }
162 catch (Exception e) {
163 throw new PortletException(e);
164 }
165 }
166
167 @Override
168 public void serveResource(
169 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
170 throws IOException, PortletException {
171
172 include(resourceFile, resourceRequest, resourceResponse);
173 }
174
175 protected void checkPath(String path) throws PortletException {
176 if (Validator.isNotNull(path) &&
177 (!path.startsWith(filePath) ||
178 !Validator.isFilePath(path, false))) {
179
180 throw new PortletException(
181 "Path " + path + " is not accessible by this portlet");
182 }
183 }
184
185 protected void declareBeans(
186 InputStream is, PortletRequest portletRequest,
187 PortletResponse portletResponse)
188 throws IOException, ScriptingException {
189
190 String script = new String(FileUtil.getBytes(is));
191
192 declareBeans(script, portletRequest, portletResponse);
193 }
194
195 protected void declareBeans(
196 String script, PortletRequest portletRequest,
197 PortletResponse portletResponse)
198 throws IOException, ScriptingException {
199
200 script = getGlobalScript() + script;
201
202 PortletConfig portletConfig = getPortletConfig();
203 PortletContext portletContext = getPortletContext();
204
205 Map<String, Object> portletObjects =
206 ScriptingHelperUtil.getPortletObjects(
207 portletConfig, portletContext, portletRequest, portletResponse);
208
209 ScriptingUtil.exec(
210 null, portletObjects, language, script, StringPool.EMPTY_ARRAY);
211 }
212
213 protected void doRender(
214 RenderRequest renderRequest, RenderResponse renderResponse)
215 throws Exception {
216
217 Object error = SessionErrors.get(renderRequest, _ERROR);
218
219 if (error != null) {
220 Exception e = (Exception)error;
221
222 writeErrorMessage(renderRequest, renderResponse, e.getMessage());
223
224 return;
225 }
226
227 super.render(renderRequest, renderResponse);
228
229 error = SessionErrors.get(renderRequest, _ERROR);
230
231 if (error != null) {
232 Exception e = (Exception)error;
233
234 writeErrorMessage(renderRequest, renderResponse, e.getMessage());
235 }
236 }
237
238 protected String getFileName(RenderRequest renderRequest) {
239 return renderRequest.getParameter("file");
240 }
241
242 protected String getGlobalScript() throws IOException {
243 if (globalScript != null) {
244 return globalScript;
245 }
246
247 if (globalFiles.length == 0) {
248 globalScript = StringPool.BLANK;
249
250 return globalScript;
251 }
252
253 StringBundler sb = new StringBundler();
254
255 for (String globalFile : globalFiles) {
256 PortletContext portletContext = getPortletContext();
257
258 InputStream inputStream = portletContext.getResourceAsStream(
259 globalFile);
260
261 if (inputStream == null) {
262 if (_log.isWarnEnabled()) {
263 _log.warn("Global file " + globalFile + " does not exist");
264 }
265 }
266
267 if (inputStream != null) {
268 String script = new String(FileUtil.getBytes(inputStream));
269
270 sb.append(script);
271 sb.append(StringPool.NEW_LINE);
272 }
273 }
274
275 globalScript = sb.toString();
276
277 return globalScript;
278 }
279
280 protected void include(
281 String path, PortletRequest portletRequest,
282 PortletResponse portletResponse)
283 throws IOException, PortletException {
284
285 checkPath(path);
286
287 PortletContext portletContext = getPortletContext();
288
289 InputStream inputStream = portletContext.getResourceAsStream(path);
290
291 if (inputStream == null) {
292 _log.error(path + " is not a valid " + language + " file");
293
294 return;
295 }
296
297 try {
298 declareBeans(inputStream, portletRequest, portletResponse);
299 }
300 catch (ScriptingException se) {
301 SessionErrors.add(portletRequest, _ERROR, se);
302 }
303 finally {
304 inputStream.close();
305 }
306 }
307
308 protected void writeErrorMessage(
309 RenderRequest renderRequest, RenderResponse renderResponse,
310 String errorMessage)
311 throws Exception {
312
313 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
314 WebKeys.THEME_DISPLAY);
315
316 PermissionChecker permissionChecker =
317 themeDisplay.getPermissionChecker();
318
319 StringBundler sb = new StringBundler(6);
320
321 sb.append("<div class=\"alert alert-error\">");
322 sb.append(themeDisplay.translate("an-unexpected-error-occurred"));
323 sb.append("</div>");
324
325 if (PortalPermissionUtil.contains(
326 permissionChecker, ActionKeys.CONFIGURATION)) {
327
328 sb.append("<pre>");
329 sb.append(HtmlUtil.escape(errorMessage));
330 sb.append("</pre>");
331 }
332
333 renderResponse.setContentType(ContentTypes.TEXT_HTML);
334
335 PortletResponseUtil.write(renderResponse, sb.toString());
336 }
337
338 protected String actionFile;
339 protected String editFile;
340 protected String filePath;
341 protected String[] globalFiles;
342 protected String globalScript;
343 protected String helpFile;
344 protected String language;
345 protected String resourceFile;
346 protected String viewFile;
347
348 private static final String _ERROR = ScriptingPortlet.class + ".ERROR";
349
350 private static final Log _log = LogFactoryUtil.getLog(
351 ScriptingPortlet.class);
352
353 }