001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.scripting.groovy;
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 groovy.lang.Binding;
023    import groovy.lang.GroovyShell;
024    import groovy.lang.Script;
025    
026    import java.util.HashMap;
027    import java.util.Map;
028    import java.util.Set;
029    
030    /**
031     * @author Alberto Montero
032     * @author Brian Wing Shun Chan
033     */
034    public class GroovyExecutor extends BaseScriptingExecutor {
035    
036            @Override
037            public void clearCache() {
038                    SingleVMPoolUtil.clear(_CACHE_NAME);
039            }
040    
041            public Map<String, Object> eval(
042                            Set<String> allowedClasses, Map<String, Object> inputObjects,
043                            Set<String> outputNames, String script)
044                    throws ScriptingException {
045    
046                    if (allowedClasses != null) {
047                            throw new ExecutionException(
048                                    "Constrained execution not supported for Groovy");
049                    }
050    
051                    Script compiledScript = getCompiledScript(script);
052    
053                    Binding binding = new Binding(inputObjects);
054    
055                    compiledScript.setBinding(binding);
056    
057                    compiledScript.run();
058    
059                    if (outputNames == null) {
060                            return null;
061                    }
062    
063                    Map<String, Object> outputObjects = new HashMap<String, Object>();
064    
065                    for (String outputName : outputNames) {
066                            outputObjects.put(outputName, binding.getVariable(outputName));
067                    }
068    
069                    return outputObjects;
070            }
071    
072            public String getLanguage() {
073                    return _LANGUAGE;
074            }
075    
076            protected Script getCompiledScript(String script) {
077                    if (_groovyShell == null) {
078                            synchronized (this) {
079                                    if (_groovyShell == null) {
080                                            _groovyShell = new GroovyShell();
081                                    }
082                            }
083                    }
084    
085                    String key = String.valueOf(script.hashCode());
086    
087                    Script compiledScript = (Script)SingleVMPoolUtil.get(_CACHE_NAME, key);
088    
089                    if (compiledScript == null) {
090                            compiledScript = _groovyShell.parse(script);
091    
092                            SingleVMPoolUtil.put(_CACHE_NAME, key, compiledScript);
093                    }
094    
095                    return compiledScript;
096            }
097    
098            private static final String _CACHE_NAME = GroovyExecutor.class.getName();
099    
100            private static final String _LANGUAGE = "groovy";
101    
102            private volatile GroovyShell _groovyShell;
103    
104    }