001    /**
002     * Copyright (c) 2000-2011 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.python;
016    
017    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
018    import com.liferay.portal.kernel.scripting.BaseScriptingExecutor;
019    import com.liferay.portal.kernel.scripting.ExecutionException;
020    import com.liferay.portal.kernel.scripting.ScriptingException;
021    
022    import java.util.HashMap;
023    import java.util.Map;
024    import java.util.Set;
025    
026    import org.python.core.CompileMode;
027    import org.python.core.Py;
028    import org.python.core.PyCode;
029    import org.python.core.PySystemState;
030    import org.python.util.InteractiveInterpreter;
031    
032    /**
033     * @author Alberto Montero
034     */
035    public class PythonExecutor extends BaseScriptingExecutor {
036    
037            @Override
038            public void clearCache() {
039                    SingleVMPoolUtil.clear(_CACHE_NAME);
040            }
041    
042            public Map<String, Object> eval(
043                            Set<String> allowedClasses, Map<String, Object> inputObjects,
044                            Set<String> outputNames, String script)
045                    throws ScriptingException {
046    
047                    if (allowedClasses != null) {
048                            throw new ExecutionException(
049                                    "Constrained execution not supported for Python");
050                    }
051    
052                    PyCode compiledScript = getCompiledScript(script);
053    
054                    InteractiveInterpreter interactiveInterpreter =
055                            new InteractiveInterpreter();
056    
057                    for (Map.Entry<String, Object> entry : inputObjects.entrySet()) {
058                            String key = entry.getKey();
059                            Object value = entry.getValue();
060    
061                            interactiveInterpreter.set(key, value);
062                    }
063    
064                    interactiveInterpreter.exec(compiledScript);
065    
066                    if (outputNames == null) {
067                            return null;
068                    }
069    
070                    Map<String, Object> outputObjects = new HashMap<String, Object>();
071    
072                    for (String outputName : outputNames) {
073                            outputObjects.put(
074                                    outputName, interactiveInterpreter.get(outputName));
075                    }
076    
077                    return outputObjects;
078            }
079    
080            public String getLanguage() {
081                    return _LANGUAGE;
082            }
083    
084            protected PyCode getCompiledScript(String script) {
085                    if (!_initialized) {
086                            synchronized (this) {
087                                    if (!_initialized) {
088                                            PySystemState.initialize();
089    
090                                            _initialized = true;
091                                    }
092                            }
093                    }
094    
095                    String key = String.valueOf(script.hashCode());
096    
097                    PyCode compiledScript = (PyCode)SingleVMPoolUtil.get(_CACHE_NAME, key);
098    
099                    if (compiledScript == null) {
100                            compiledScript = Py.compile_flags(
101                                    script, "<string>", CompileMode.exec, Py.getCompilerFlags());
102    
103                            SingleVMPoolUtil.put(_CACHE_NAME, key, compiledScript);
104                    }
105    
106                    return compiledScript;
107            }
108    
109            private static final String _CACHE_NAME = PythonExecutor.class.getName();
110    
111            private static final String _LANGUAGE = "python";
112    
113            private volatile boolean _initialized;
114    
115    }