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.ClassLoaderPool;
027 import com.liferay.portal.kernel.util.StringBundler;
028 import com.liferay.portal.kernel.util.StringPool;
029
030 import java.io.IOException;
031 import java.io.LineNumberReader;
032
033 import java.util.Map;
034 import java.util.Set;
035 import java.util.concurrent.ConcurrentHashMap;
036
037 import org.apache.commons.lang.time.StopWatch;
038
039 import org.python.core.Py;
040 import org.python.core.PyFile;
041 import org.python.core.PySyntaxError;
042
043
048 @DoPrivileged
049 public class ScriptingImpl implements Scripting {
050
051 public void addScriptingExecutor(
052 String language, ScriptingExecutor scriptingExecutor) {
053
054 _scriptingExecutors.put(language, scriptingExecutor);
055 }
056
057 @Override
058 public void clearCache(String language) throws ScriptingException {
059 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
060
061 if (scriptingExecutor == null) {
062 throw new UnsupportedLanguageException(language);
063 }
064
065 scriptingExecutor.clearCache();
066 }
067
068 @Override
069 public Map<String, Object> eval(
070 Set<String> allowedClasses, Map<String, Object> inputObjects,
071 Set<String> outputNames, String language, String script,
072 String... servletContextNames)
073 throws ScriptingException {
074
075 ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
076
077 if (scriptingExecutor == null) {
078 throw new UnsupportedLanguageException(language);
079 }
080
081 StopWatch stopWatch = new StopWatch();
082
083 stopWatch.start();
084
085 try {
086 return scriptingExecutor.eval(
087 allowedClasses, inputObjects, outputNames, script,
088 getClassLoaders(servletContextNames));
089 }
090 catch (Exception e) {
091 throw new ScriptingException(getErrorMessage(script, e), e);
092 }
093 finally {
094 if (_log.isDebugEnabled()) {
095 _log.debug(
096 "Evaluated script in " + stopWatch.getTime() + " ms");
097 }
098 }
099 }
100
101 @Override
102 public void exec(
103 Set<String> allowedClasses, Map<String, Object> inputObjects,
104 String language, String script, String... servletContextNames)
105 throws ScriptingException {
106
107 eval(
108 allowedClasses, inputObjects, null, language, script,
109 servletContextNames);
110 }
111
112 @Override
113 public Set<String> getSupportedLanguages() {
114 return _scriptingExecutors.keySet();
115 }
116
117 public void setScriptingExecutors(
118 Map<String, ScriptingExecutor> scriptingExecutors) {
119
120 for (Map.Entry<String, ScriptingExecutor> entry :
121 scriptingExecutors.entrySet()) {
122
123 _scriptingExecutors.put(entry.getKey(), entry.getValue());
124 }
125 }
126
127 protected ClassLoader[] getClassLoaders(String[] servletContextNames) {
128 ClassLoader[] classLoaders =
129 new ClassLoader[servletContextNames.length];
130
131 for (int i = 0; i < servletContextNames.length; i++) {
132 classLoaders[i] = ClassLoaderPool.getClassLoader(
133 servletContextNames[i]);
134 }
135
136 return classLoaders;
137 }
138
139 protected String getErrorMessage(Exception e) {
140 String message = e.getMessage();
141
142 if (e instanceof PySyntaxError) {
143 PySyntaxError pySyntaxError = (PySyntaxError)e;
144
145 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
146 new UnsyncByteArrayOutputStream();
147
148 Py.displayException(
149 pySyntaxError.type, pySyntaxError.value,
150 pySyntaxError.traceback,
151 new PyFile(unsyncByteArrayOutputStream));
152
153 message = unsyncByteArrayOutputStream.toString();
154 }
155
156 return message;
157 }
158
159 protected String getErrorMessage(String script, Exception e) {
160 StringBundler sb = new StringBundler();
161
162 sb.append(getErrorMessage(e));
163 sb.append(StringPool.NEW_LINE);
164
165 try {
166 LineNumberReader lineNumberReader = new LineNumberReader(
167 new UnsyncStringReader(script));
168
169 while (true) {
170 String line = lineNumberReader.readLine();
171
172 if (line == null) {
173 break;
174 }
175
176 sb.append("Line ");
177 sb.append(lineNumberReader.getLineNumber());
178 sb.append(": ");
179 sb.append(line);
180 sb.append(StringPool.NEW_LINE);
181 }
182 }
183 catch (IOException ioe) {
184 sb.setIndex(0);
185
186 sb.append(getErrorMessage(e));
187 sb.append(StringPool.NEW_LINE);
188 sb.append(script);
189 }
190
191 return sb.toString();
192 }
193
194 private static Log _log = LogFactoryUtil.getLog(ScriptingImpl.class);
195
196 private Map<String, ScriptingExecutor> _scriptingExecutors =
197 new ConcurrentHashMap<String, ScriptingExecutor>();
198
199 }