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