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 filePath = StringPool.SLASH;
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(null, portletObjects, language, script);
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 Log _log = LogFactoryUtil.getLog(ScriptingPortlet.class);
351
352 }