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.security.permission.ActionKeys;
024 import com.liferay.portal.kernel.security.permission.PermissionChecker;
025 import com.liferay.portal.kernel.service.permission.PortalPermissionUtil;
026 import com.liferay.portal.kernel.servlet.SessionErrors;
027 import com.liferay.portal.kernel.theme.ThemeDisplay;
028 import com.liferay.portal.kernel.util.ContentTypes;
029 import com.liferay.portal.kernel.util.FileUtil;
030 import com.liferay.portal.kernel.util.HtmlUtil;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.util.WebKeys;
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(null, portletObjects, language, script);
210 }
211
212 protected void doRender(
213 RenderRequest renderRequest, RenderResponse renderResponse)
214 throws Exception {
215
216 Object error = SessionErrors.get(renderRequest, _ERROR);
217
218 if (error != null) {
219 Exception e = (Exception)error;
220
221 writeErrorMessage(renderRequest, renderResponse, e.getMessage());
222
223 return;
224 }
225
226 super.render(renderRequest, renderResponse);
227
228 error = SessionErrors.get(renderRequest, _ERROR);
229
230 if (error != null) {
231 Exception e = (Exception)error;
232
233 writeErrorMessage(renderRequest, renderResponse, e.getMessage());
234 }
235 }
236
237 protected String getFileName(RenderRequest renderRequest) {
238 return renderRequest.getParameter("file");
239 }
240
241 protected String getGlobalScript() throws IOException {
242 if (globalScript != null) {
243 return globalScript;
244 }
245
246 if (globalFiles.length == 0) {
247 globalScript = StringPool.BLANK;
248
249 return globalScript;
250 }
251
252 StringBundler sb = new StringBundler();
253
254 for (String globalFile : globalFiles) {
255 PortletContext portletContext = getPortletContext();
256
257 InputStream inputStream = portletContext.getResourceAsStream(
258 globalFile);
259
260 if (inputStream == null) {
261 if (_log.isWarnEnabled()) {
262 _log.warn("Global file " + globalFile + " does not exist");
263 }
264 }
265
266 if (inputStream != null) {
267 String script = new String(FileUtil.getBytes(inputStream));
268
269 sb.append(script);
270 sb.append(StringPool.NEW_LINE);
271 }
272 }
273
274 globalScript = sb.toString();
275
276 return globalScript;
277 }
278
279 protected void include(
280 String path, PortletRequest portletRequest,
281 PortletResponse portletResponse)
282 throws IOException, PortletException {
283
284 checkPath(path);
285
286 PortletContext portletContext = getPortletContext();
287
288 InputStream inputStream = portletContext.getResourceAsStream(path);
289
290 if (inputStream == null) {
291 _log.error(path + " is not a valid " + language + " file");
292
293 return;
294 }
295
296 try {
297 declareBeans(inputStream, portletRequest, portletResponse);
298 }
299 catch (ScriptingException se) {
300 SessionErrors.add(portletRequest, _ERROR, se);
301 }
302 finally {
303 inputStream.close();
304 }
305 }
306
307 protected void writeErrorMessage(
308 RenderRequest renderRequest, RenderResponse renderResponse,
309 String errorMessage)
310 throws Exception {
311
312 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
313 WebKeys.THEME_DISPLAY);
314
315 PermissionChecker permissionChecker =
316 themeDisplay.getPermissionChecker();
317
318 StringBundler sb = new StringBundler(6);
319
320 sb.append("<div class=\"alert alert-error\">");
321 sb.append(themeDisplay.translate("an-unexpected-error-occurred"));
322 sb.append("</div>");
323
324 if (PortalPermissionUtil.contains(
325 permissionChecker, ActionKeys.CONFIGURATION)) {
326
327 sb.append("<pre>");
328 sb.append(HtmlUtil.escape(errorMessage));
329 sb.append("</pre>");
330 }
331
332 renderResponse.setContentType(ContentTypes.TEXT_HTML);
333
334 PortletResponseUtil.write(renderResponse, sb.toString());
335 }
336
337 protected String actionFile;
338 protected String editFile;
339 protected String filePath;
340 protected String[] globalFiles;
341 protected String globalScript;
342 protected String helpFile;
343 protected String language;
344 protected String resourceFile;
345 protected String viewFile;
346
347 private static final String _ERROR = ScriptingPortlet.class + ".ERROR";
348
349 private static final Log _log = LogFactoryUtil.getLog(
350 ScriptingPortlet.class);
351
352 }