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 public void addScriptingExecutor(
062 String language, ScriptingExecutor scriptingExecutor) {
063
064 _scriptingExecutors.put(language, scriptingExecutor);
065 }
066
067 public void clearCache(String language) throws ScriptingException {
068 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
069
070 if (scriptingExecutor == null) {
071 throw new UnsupportedLanguageException(language);
072 }
073
074 scriptingExecutor.clearCache();
075 }
076
077 public Map<String, Object> eval(
078 Set<String> allowedClasses, Map<String, Object> inputObjects,
079 Set<String> outputNames, String language, String script,
080 ClassLoader... classLoaders)
081 throws ScriptingException {
082
083 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
084
085 if (scriptingExecutor == null) {
086 throw new UnsupportedLanguageException(language);
087 }
088
089 StopWatch stopWatch = null;
090
091 if (_log.isDebugEnabled()) {
092 stopWatch = new StopWatch();
093
094 stopWatch.start();
095 }
096
097 try {
098 return scriptingExecutor.eval(
099 allowedClasses, inputObjects, outputNames, script,
100 classLoaders);
101 }
102 catch (Exception e) {
103 throw new ScriptingException(getErrorMessage(script, e), e);
104 }
105 finally {
106 if (_log.isDebugEnabled()) {
107 _log.debug(
108 "Evaluated script in " + stopWatch.getTime() + " ms");
109 }
110 }
111 }
112
113 public void exec(
114 Set<String> allowedClasses, Map<String, Object> inputObjects,
115 String language, String script, ClassLoader... classLoaders)
116 throws ScriptingException {
117
118 eval(
119 allowedClasses, inputObjects, null, language, script, classLoaders);
120 }
121
122 public Map<String, Object> getPortletObjects(
123 PortletConfig portletConfig, PortletContext portletContext,
124 PortletRequest portletRequest, PortletResponse portletResponse) {
125
126 Map<String, Object> objects = new HashMap<String, Object>();
127
128 objects.put("portletConfig", portletConfig);
129 objects.put("portletContext", portletContext);
130 objects.put("preferences", portletRequest.getPreferences());
131
132 if (portletRequest instanceof ActionRequest) {
133 objects.put("actionRequest", portletRequest);
134 }
135 else if (portletRequest instanceof RenderRequest) {
136 objects.put("renderRequest", portletRequest);
137 }
138 else if (portletRequest instanceof ResourceRequest) {
139 objects.put("resourceRequest", portletRequest);
140 }
141 else {
142 objects.put("portletRequest", portletRequest);
143 }
144
145 if (portletResponse instanceof ActionResponse) {
146 objects.put("actionResponse", portletResponse);
147 }
148 else if (portletResponse instanceof RenderResponse) {
149 objects.put("renderResponse", portletResponse);
150 }
151 else if (portletResponse instanceof ResourceResponse) {
152 objects.put("resourceResponse", portletResponse);
153 }
154 else {
155 objects.put("portletResponse", portletResponse);
156 }
157
158 objects.put(
159 "userInfo", portletRequest.getAttribute(PortletRequest.USER_INFO));
160
161 return objects;
162 }
163
164 public Set<String> getSupportedLanguages() {
165 return _scriptingExecutors.keySet();
166 }
167
168 public void setScriptingExecutors(
169 Map<String, ScriptingExecutor> scriptingExecutors) {
170
171 for (Map.Entry<String, ScriptingExecutor> entry :
172 scriptingExecutors.entrySet()) {
173
174 _scriptingExecutors.put(entry.getKey(), entry.getValue());
175 }
176 }
177
178 protected String getErrorMessage(Exception e) {
179 String message = e.getMessage();
180
181 if (e instanceof PySyntaxError) {
182 PySyntaxError pySyntaxError = (PySyntaxError)e;
183
184 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
185 new UnsyncByteArrayOutputStream();
186
187 Py.displayException(
188 pySyntaxError.type, pySyntaxError.value,
189 pySyntaxError.traceback,
190 new PyFile(unsyncByteArrayOutputStream));
191
192 message = unsyncByteArrayOutputStream.toString();
193 }
194
195 return message;
196 }
197
198 protected String getErrorMessage(String script, Exception e) {
199 StringBundler sb = new StringBundler();
200
201 sb.append(getErrorMessage(e));
202 sb.append(StringPool.NEW_LINE);
203
204 try {
205 LineNumberReader lineNumberReader = new LineNumberReader(
206 new UnsyncStringReader(script));
207
208 while (true) {
209 String line = lineNumberReader.readLine();
210
211 if (line == null) {
212 break;
213 }
214
215 sb.append("Line ");
216 sb.append(lineNumberReader.getLineNumber());
217 sb.append(": ");
218 sb.append(line);
219 sb.append(StringPool.NEW_LINE);
220 }
221 }
222 catch (IOException ioe) {
223 sb.setIndex(0);
224
225 sb.append(getErrorMessage(e));
226 sb.append(StringPool.NEW_LINE);
227 sb.append(script);
228 }
229
230 return sb.toString();
231 }
232
233 private static Log _log = LogFactoryUtil.getLog(ScriptingImpl.class);
234
235 private Map<String, ScriptingExecutor> _scriptingExecutors =
236 new ConcurrentHashMap<String, ScriptingExecutor>();
237
238 }