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 = null;
082
083 if (_log.isDebugEnabled()) {
084 stopWatch = new StopWatch();
085
086 stopWatch.start();
087 }
088
089 try {
090 return scriptingExecutor.eval(
091 allowedClasses, inputObjects, outputNames, script,
092 getClassLoaders(servletContextNames));
093 }
094 catch (Exception e) {
095 throw new ScriptingException(getErrorMessage(script, e), e);
096 }
097 finally {
098 if (_log.isDebugEnabled()) {
099 _log.debug(
100 "Evaluated script in " + stopWatch.getTime() + " ms");
101 }
102 }
103 }
104
105 @Override
106 public void exec(
107 Set<String> allowedClasses, Map<String, Object> inputObjects,
108 String language, String script, String... servletContextNames)
109 throws ScriptingException {
110
111 eval(
112 allowedClasses, inputObjects, null, language, script,
113 servletContextNames);
114 }
115
116 @Override
117 public Set<String> getSupportedLanguages() {
118 return _scriptingExecutors.keySet();
119 }
120
121 public void setScriptingExecutors(
122 Map<String, ScriptingExecutor> scriptingExecutors) {
123
124 for (Map.Entry<String, ScriptingExecutor> entry :
125 scriptingExecutors.entrySet()) {
126
127 _scriptingExecutors.put(entry.getKey(), entry.getValue());
128 }
129 }
130
131 protected ClassLoader[] getClassLoaders(String[] servletContextNames) {
132 ClassLoader[] classLoaders =
133 new ClassLoader[servletContextNames.length];
134
135 for (int i = 0; i < servletContextNames.length; i++) {
136 classLoaders[i] = ClassLoaderPool.getClassLoader(
137 servletContextNames[i]);
138 }
139
140 return classLoaders;
141 }
142
143 protected String getErrorMessage(Exception e) {
144 String message = e.getMessage();
145
146 if (e instanceof PySyntaxError) {
147 PySyntaxError pySyntaxError = (PySyntaxError)e;
148
149 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
150 new UnsyncByteArrayOutputStream();
151
152 Py.displayException(
153 pySyntaxError.type, pySyntaxError.value,
154 pySyntaxError.traceback,
155 new PyFile(unsyncByteArrayOutputStream));
156
157 message = unsyncByteArrayOutputStream.toString();
158 }
159
160 return message;
161 }
162
163 protected String getErrorMessage(String script, Exception e) {
164 StringBundler sb = new StringBundler();
165
166 sb.append(getErrorMessage(e));
167 sb.append(StringPool.NEW_LINE);
168
169 try {
170 LineNumberReader lineNumberReader = new LineNumberReader(
171 new UnsyncStringReader(script));
172
173 while (true) {
174 String line = lineNumberReader.readLine();
175
176 if (line == null) {
177 break;
178 }
179
180 sb.append("Line ");
181 sb.append(lineNumberReader.getLineNumber());
182 sb.append(": ");
183 sb.append(line);
184 sb.append(StringPool.NEW_LINE);
185 }
186 }
187 catch (IOException ioe) {
188 sb.setIndex(0);
189
190 sb.append(getErrorMessage(e));
191 sb.append(StringPool.NEW_LINE);
192 sb.append(script);
193 }
194
195 return sb.toString();
196 }
197
198 private static Log _log = LogFactoryUtil.getLog(ScriptingImpl.class);
199
200 private Map<String, ScriptingExecutor> _scriptingExecutors =
201 new ConcurrentHashMap<String, ScriptingExecutor>();
202
203 }