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