001
014
015 package com.liferay.portal.scripting;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.scripting.Scripting;
022 import com.liferay.portal.kernel.scripting.ScriptingException;
023 import com.liferay.portal.kernel.scripting.ScriptingExecutor;
024 import com.liferay.portal.kernel.scripting.UnsupportedLanguageException;
025 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028
029 import java.io.IOException;
030 import java.io.LineNumberReader;
031
032 import java.util.HashMap;
033 import java.util.Map;
034 import java.util.Set;
035 import java.util.concurrent.ConcurrentHashMap;
036
037 import javax.portlet.ActionRequest;
038 import javax.portlet.ActionResponse;
039 import javax.portlet.PortletConfig;
040 import javax.portlet.PortletContext;
041 import javax.portlet.PortletRequest;
042 import javax.portlet.PortletResponse;
043 import javax.portlet.RenderRequest;
044 import javax.portlet.RenderResponse;
045 import javax.portlet.ResourceRequest;
046 import javax.portlet.ResourceResponse;
047
048 import org.apache.commons.lang.time.StopWatch;
049
050 import org.python.core.Py;
051 import org.python.core.PyFile;
052 import org.python.core.PySyntaxError;
053
054
058 @DoPrivileged
059 public class ScriptingImpl implements Scripting {
060
061 @Override
062 public void addScriptingExecutor(
063 String language, ScriptingExecutor scriptingExecutor) {
064
065 _scriptingExecutors.put(language, scriptingExecutor);
066 }
067
068 @Override
069 public void clearCache(String language) throws ScriptingException {
070 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
071
072 if (scriptingExecutor == null) {
073 throw new UnsupportedLanguageException(language);
074 }
075
076 scriptingExecutor.clearCache();
077 }
078
079 @Override
080 public Map<String, Object> eval(
081 Set<String> allowedClasses, Map<String, Object> inputObjects,
082 Set<String> outputNames, String language, String script,
083 ClassLoader... classLoaders)
084 throws ScriptingException {
085
086 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
087
088 if (scriptingExecutor == null) {
089 throw new UnsupportedLanguageException(language);
090 }
091
092 StopWatch stopWatch = null;
093
094 if (_log.isDebugEnabled()) {
095 stopWatch = new StopWatch();
096
097 stopWatch.start();
098 }
099
100 try {
101 return scriptingExecutor.eval(
102 allowedClasses, inputObjects, outputNames, script,
103 classLoaders);
104 }
105 catch (Exception e) {
106 throw new ScriptingException(getErrorMessage(script, e), e);
107 }
108 finally {
109 if (_log.isDebugEnabled()) {
110 _log.debug(
111 "Evaluated script in " + stopWatch.getTime() + " ms");
112 }
113 }
114 }
115
116 @Override
117 public void exec(
118 Set<String> allowedClasses, Map<String, Object> inputObjects,
119 String language, String script, ClassLoader... classLoaders)
120 throws ScriptingException {
121
122 eval(
123 allowedClasses, inputObjects, null, language, script, classLoaders);
124 }
125
126 @Override
127 public Map<String, Object> getPortletObjects(
128 PortletConfig portletConfig, PortletContext portletContext,
129 PortletRequest portletRequest, PortletResponse portletResponse) {
130
131 Map<String, Object> objects = new HashMap<String, Object>();
132
133 objects.put("portletConfig", portletConfig);
134 objects.put("portletContext", portletContext);
135 objects.put("preferences", portletRequest.getPreferences());
136
137 if (portletRequest instanceof ActionRequest) {
138 objects.put("actionRequest", portletRequest);
139 }
140 else if (portletRequest instanceof RenderRequest) {
141 objects.put("renderRequest", portletRequest);
142 }
143 else if (portletRequest instanceof ResourceRequest) {
144 objects.put("resourceRequest", portletRequest);
145 }
146 else {
147 objects.put("portletRequest", portletRequest);
148 }
149
150 if (portletResponse instanceof ActionResponse) {
151 objects.put("actionResponse", portletResponse);
152 }
153 else if (portletResponse instanceof RenderResponse) {
154 objects.put("renderResponse", portletResponse);
155 }
156 else if (portletResponse instanceof ResourceResponse) {
157 objects.put("resourceResponse", portletResponse);
158 }
159 else {
160 objects.put("portletResponse", portletResponse);
161 }
162
163 objects.put(
164 "userInfo", portletRequest.getAttribute(PortletRequest.USER_INFO));
165
166 return objects;
167 }
168
169 @Override
170 public Set<String> getSupportedLanguages() {
171 return _scriptingExecutors.keySet();
172 }
173
174 @Override
175 public void setScriptingExecutors(
176 Map<String, ScriptingExecutor> scriptingExecutors) {
177
178 for (Map.Entry<String, ScriptingExecutor> entry :
179 scriptingExecutors.entrySet()) {
180
181 _scriptingExecutors.put(entry.getKey(), entry.getValue());
182 }
183 }
184
185 protected String getErrorMessage(Exception e) {
186 String message = e.getMessage();
187
188 if (e instanceof PySyntaxError) {
189 PySyntaxError pySyntaxError = (PySyntaxError)e;
190
191 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
192 new UnsyncByteArrayOutputStream();
193
194 Py.displayException(
195 pySyntaxError.type, pySyntaxError.value,
196 pySyntaxError.traceback,
197 new PyFile(unsyncByteArrayOutputStream));
198
199 message = unsyncByteArrayOutputStream.toString();
200 }
201
202 return message;
203 }
204
205 protected String getErrorMessage(String script, Exception e) {
206 StringBundler sb = new StringBundler();
207
208 sb.append(getErrorMessage(e));
209 sb.append(StringPool.NEW_LINE);
210
211 try {
212 LineNumberReader lineNumberReader = new LineNumberReader(
213 new UnsyncStringReader(script));
214
215 while (true) {
216 String line = lineNumberReader.readLine();
217
218 if (line == null) {
219 break;
220 }
221
222 sb.append("Line ");
223 sb.append(lineNumberReader.getLineNumber());
224 sb.append(": ");
225 sb.append(line);
226 sb.append(StringPool.NEW_LINE);
227 }
228 }
229 catch (IOException ioe) {
230 sb.setIndex(0);
231
232 sb.append(getErrorMessage(e));
233 sb.append(StringPool.NEW_LINE);
234 sb.append(script);
235 }
236
237 return sb.toString();
238 }
239
240 private static Log _log = LogFactoryUtil.getLog(ScriptingImpl.class);
241
242 private Map<String, ScriptingExecutor> _scriptingExecutors =
243 new ConcurrentHashMap<String, ScriptingExecutor>();
244
245 }