001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
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.scripting.Scripting;
020    import com.liferay.portal.kernel.scripting.ScriptingException;
021    import com.liferay.portal.kernel.scripting.ScriptingExecutor;
022    import com.liferay.portal.kernel.scripting.UnsupportedLanguageException;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    
026    import java.io.IOException;
027    import java.io.LineNumberReader;
028    
029    import java.util.HashMap;
030    import java.util.Map;
031    import java.util.Set;
032    import java.util.concurrent.ConcurrentHashMap;
033    
034    import javax.portlet.ActionRequest;
035    import javax.portlet.ActionResponse;
036    import javax.portlet.PortletConfig;
037    import javax.portlet.PortletContext;
038    import javax.portlet.PortletRequest;
039    import javax.portlet.PortletResponse;
040    import javax.portlet.RenderRequest;
041    import javax.portlet.RenderResponse;
042    import javax.portlet.ResourceRequest;
043    import javax.portlet.ResourceResponse;
044    
045    import org.python.core.Py;
046    import org.python.core.PyFile;
047    import org.python.core.PySyntaxError;
048    
049    /**
050     * @author Alberto Montero
051     * @author Brian Wing Shun Chan
052     */
053    public class ScriptingImpl implements Scripting {
054    
055            public void addScriptionExecutor(
056                    String language, ScriptingExecutor scriptingExecutor) {
057    
058                    _scriptingExecutors.put(language, scriptingExecutor);
059            }
060    
061            public void clearCache(String language) throws ScriptingException {
062                    ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
063    
064                    if (scriptingExecutor == null) {
065                            throw new UnsupportedLanguageException(language);
066                    }
067    
068                    scriptingExecutor.clearCache();
069            }
070    
071            public Map<String, Object> eval(
072                            Set<String> allowedClasses, Map<String, Object> inputObjects,
073                            Set<String> outputNames, String language, String script)
074                    throws ScriptingException {
075    
076                    ScriptingExecutor scriptingExecutor = _scriptingExecutors.get(language);
077    
078                    if (scriptingExecutor == null) {
079                            throw new UnsupportedLanguageException(language);
080                    }
081    
082                    try {
083                            return scriptingExecutor.eval(
084                                    allowedClasses, inputObjects, outputNames, script);
085                    }
086                    catch (Exception e) {
087                            throw new ScriptingException(getErrorMessage(script, e), e);
088                    }
089            }
090    
091            public void exec(
092                            Set<String> allowedClasses, Map<String, Object> inputObjects,
093                            String language, String script)
094                    throws ScriptingException {
095    
096                    eval(allowedClasses, inputObjects, null, language, script);
097            }
098    
099            public Map<String, Object> getPortletObjects(
100                    PortletConfig portletConfig, PortletContext portletContext,
101                    PortletRequest portletRequest, PortletResponse portletResponse) {
102    
103                    Map<String, Object> objects = new HashMap<String, Object>();
104    
105                    objects.put("portletConfig", portletConfig);
106                    objects.put("portletContext", portletContext);
107                    objects.put("preferences", portletRequest.getPreferences());
108    
109                    if (portletRequest instanceof ActionRequest) {
110                            objects.put("actionRequest", portletRequest);
111                    }
112                    else if (portletRequest instanceof RenderRequest) {
113                            objects.put("renderRequest", portletRequest);
114                    }
115                    else if (portletRequest instanceof ResourceRequest) {
116                            objects.put("resourceRequest", portletRequest);
117                    }
118                    else {
119                            objects.put("portletRequest", portletRequest);
120                    }
121    
122                    if (portletResponse instanceof ActionResponse) {
123                            objects.put("actionResponse", portletResponse);
124                    }
125                    else if (portletResponse instanceof RenderResponse) {
126                            objects.put("renderResponse", portletResponse);
127                    }
128                    else if (portletResponse instanceof ResourceResponse) {
129                            objects.put("resourceResponse", portletResponse);
130                    }
131                    else {
132                            objects.put("portletResponse", portletResponse);
133                    }
134    
135                    objects.put(
136                            "userInfo", portletRequest.getAttribute(PortletRequest.USER_INFO));
137    
138                    return objects;
139            }
140    
141            public Set<String> getSupportedLanguages() {
142                    return _scriptingExecutors.keySet();
143            }
144    
145            public void setScriptingExecutors(
146                    Map<String, ScriptingExecutor> scriptingExecutors) {
147    
148                    for (Map.Entry<String, ScriptingExecutor> entry :
149                                    scriptingExecutors.entrySet()) {
150    
151                            _scriptingExecutors.put(entry.getKey(), entry.getValue());
152                    }
153            }
154    
155            protected String getErrorMessage(Exception e) {
156                    String message = e.getMessage();
157    
158                    if (e instanceof PySyntaxError) {
159                            PySyntaxError pySyntaxError = (PySyntaxError)e;
160    
161                            UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
162                                    new UnsyncByteArrayOutputStream();
163    
164                            Py.displayException(
165                                    pySyntaxError.type, pySyntaxError.value,
166                                    pySyntaxError.traceback,
167                                    new PyFile(unsyncByteArrayOutputStream));
168    
169                            message = unsyncByteArrayOutputStream.toString();
170                    }
171    
172                    return message;
173            }
174    
175            protected String getErrorMessage(String script, Exception e) {
176                    StringBundler sb = new StringBundler();
177    
178                    sb.append(getErrorMessage(e));
179                    sb.append(StringPool.NEW_LINE);
180    
181                    try{
182                            LineNumberReader lineNumberReader = new LineNumberReader(
183                                    new UnsyncStringReader(script));
184    
185                            while (true) {
186                                    String line = lineNumberReader.readLine();
187    
188                                    if (line == null) {
189                                            break;
190                                    }
191    
192                                    sb.append("Line ");
193                                    sb.append(lineNumberReader.getLineNumber());
194                                    sb.append(": ");
195                                    sb.append(line);
196                                    sb.append(StringPool.NEW_LINE);
197                            }
198                    }
199                    catch (IOException ioe) {
200                            sb.setIndex(0);
201    
202                            sb.append(getErrorMessage(e));
203                            sb.append(StringPool.NEW_LINE);
204                            sb.append(script);
205                    }
206    
207                    return sb.toString();
208            }
209    
210            private Map<String, ScriptingExecutor> _scriptingExecutors =
211                    new ConcurrentHashMap<String, ScriptingExecutor>();
212    
213    }