1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.scripting;
16  
17  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
18  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19  import com.liferay.portal.kernel.scripting.Scripting;
20  import com.liferay.portal.kernel.scripting.ScriptingException;
21  import com.liferay.portal.kernel.scripting.ScriptingExecutor;
22  import com.liferay.portal.kernel.scripting.UnsupportedLanguageException;
23  import com.liferay.portal.kernel.util.StringBundler;
24  import com.liferay.portal.kernel.util.StringPool;
25  
26  import java.io.IOException;
27  import java.io.LineNumberReader;
28  
29  import java.util.HashMap;
30  import java.util.Map;
31  import java.util.Set;
32  import java.util.concurrent.ConcurrentHashMap;
33  
34  import javax.portlet.ActionRequest;
35  import javax.portlet.ActionResponse;
36  import javax.portlet.PortletConfig;
37  import javax.portlet.PortletContext;
38  import javax.portlet.PortletRequest;
39  import javax.portlet.PortletResponse;
40  import javax.portlet.RenderRequest;
41  import javax.portlet.RenderResponse;
42  import javax.portlet.ResourceRequest;
43  import javax.portlet.ResourceResponse;
44  
45  import org.python.core.Py;
46  import org.python.core.PyFile;
47  import org.python.core.PySyntaxError;
48  
49  /**
50   * <a href="ScriptingImpl.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Alberto Montero
53   * @author Brian Wing Shun Chan
54   */
55  public class ScriptingImpl implements Scripting {
56  
57      public void addScriptionExecutor(
58          String language, ScriptingExecutor scriptingExecutor) {
59  
60          _scriptingExecutors.put(language, scriptingExecutor);
61      }
62  
63      public void clearCache(String language) throws ScriptingException {
64          ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
65  
66          if (scriptingExecutor == null) {
67              throw new UnsupportedLanguageException(language);
68          }
69  
70          scriptingExecutor.clearCache();
71      }
72  
73      public Map<String, Object> eval(
74              Set<String> allowedClasses, Map<String, Object> inputObjects,
75              Set<String> outputNames, String language, String script)
76          throws ScriptingException {
77  
78          ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
79  
80          if (scriptingExecutor == null) {
81              throw new UnsupportedLanguageException(language);
82          }
83  
84          try {
85              return scriptingExecutor.eval(
86                  allowedClasses, inputObjects, outputNames, script);
87          }
88          catch (Exception e) {
89              throw new ScriptingException(getErrorMessage(script, e), e);
90          }
91      }
92  
93      public void exec(
94              Set<String> allowedClasses, Map<String, Object> inputObjects,
95              String language, String script)
96          throws ScriptingException {
97  
98          eval(allowedClasses, inputObjects, null, language, script);
99      }
100 
101     public Map<String, Object> getPortletObjects(
102         PortletConfig portletConfig, PortletContext portletContext,
103         PortletRequest portletRequest, PortletResponse portletResponse) {
104 
105         Map<String, Object> objects = new HashMap<String, Object>();
106 
107         objects.put("portletConfig", portletConfig);
108         objects.put("portletContext", portletContext);
109         objects.put("preferences", portletRequest.getPreferences());
110 
111         if (portletRequest instanceof ActionRequest) {
112             objects.put("actionRequest", portletRequest);
113         }
114         else if (portletRequest instanceof RenderRequest) {
115             objects.put("renderRequest", portletRequest);
116         }
117         else if (portletRequest instanceof ResourceRequest) {
118             objects.put("resourceRequest", portletRequest);
119         }
120         else {
121             objects.put("portletRequest", portletRequest);
122         }
123 
124         if (portletResponse instanceof ActionResponse) {
125             objects.put("actionResponse", portletResponse);
126         }
127         else if (portletResponse instanceof RenderResponse) {
128             objects.put("renderResponse", portletResponse);
129         }
130         else if (portletResponse instanceof ResourceResponse) {
131             objects.put("resourceResponse", portletResponse);
132         }
133         else {
134             objects.put("portletResponse", portletResponse);
135         }
136 
137         objects.put(
138             "userInfo", portletRequest.getAttribute(PortletRequest.USER_INFO));
139 
140         return objects;
141     }
142 
143     public Set<String> getSupportedLanguages() {
144         return _scriptingExecutors.keySet();
145     }
146 
147     public void setScriptingExecutors(
148         Map<String, ScriptingExecutor> scriptingExecutors) {
149 
150         for (Map.Entry<String, ScriptingExecutor> entry :
151                 scriptingExecutors.entrySet()) {
152 
153             _scriptingExecutors.put(entry.getKey(), entry.getValue());
154         }
155     }
156 
157     protected String getErrorMessage(Exception e) {
158         String message = e.getMessage();
159 
160         if (e instanceof PySyntaxError) {
161             PySyntaxError pySyntaxError = (PySyntaxError)e;
162 
163             UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
164                 new UnsyncByteArrayOutputStream();
165 
166             Py.displayException(
167                 pySyntaxError.type, pySyntaxError.value,
168                 pySyntaxError.traceback,
169                 new PyFile(unsyncByteArrayOutputStream));
170 
171             message = unsyncByteArrayOutputStream.toString();
172         }
173 
174         return message;
175     }
176 
177     protected String getErrorMessage(String script, Exception e) {
178         StringBundler sb = new StringBundler();
179 
180         sb.append(getErrorMessage(e));
181         sb.append(StringPool.NEW_LINE);
182 
183         try{
184             LineNumberReader lineNumberReader = new LineNumberReader(
185                 new UnsyncStringReader(script));
186 
187             while (true) {
188                 String line = lineNumberReader.readLine();
189 
190                 if (line == null) {
191                     break;
192                 }
193 
194                 sb.append("Line ");
195                 sb.append(lineNumberReader.getLineNumber());
196                 sb.append(": ");
197                 sb.append(line);
198                 sb.append(StringPool.NEW_LINE);
199             }
200         }
201         catch (IOException ioe) {
202             sb.setIndex(0);
203 
204             sb.append(getErrorMessage(e));
205             sb.append(StringPool.NEW_LINE);
206             sb.append(script);
207         }
208 
209         return sb.toString();
210     }
211 
212     private Map<String, ScriptingExecutor> _scriptingExecutors =
213         new ConcurrentHashMap<String, ScriptingExecutor>();
214 
215 }