001
014
015 package com.liferay.portal.scripting.groovy;
016
017 import com.liferay.portal.kernel.cache.PortalCache;
018 import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
019 import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap;
020 import com.liferay.portal.kernel.memory.FinalizeManager;
021 import com.liferay.portal.kernel.scripting.BaseScriptingExecutor;
022 import com.liferay.portal.kernel.scripting.ExecutionException;
023 import com.liferay.portal.kernel.scripting.ScriptingException;
024 import com.liferay.portal.kernel.util.AggregateClassLoader;
025 import com.liferay.portal.kernel.util.ArrayUtil;
026 import com.liferay.portal.util.ClassLoaderUtil;
027
028 import groovy.lang.Binding;
029 import groovy.lang.GroovyShell;
030 import groovy.lang.Script;
031
032 import java.util.HashMap;
033 import java.util.Map;
034 import java.util.Set;
035 import java.util.concurrent.ConcurrentMap;
036
037
041 public class GroovyExecutor extends BaseScriptingExecutor {
042
043 @Override
044 public void clearCache() {
045 _portalCache.removeAll();
046 }
047
048 @Override
049 public Map<String, Object> eval(
050 Set<String> allowedClasses, Map<String, Object> inputObjects,
051 Set<String> outputNames, String script, ClassLoader... classLoaders)
052 throws ScriptingException {
053
054 if (allowedClasses != null) {
055 throw new ExecutionException(
056 "Constrained execution not supported for Groovy");
057 }
058
059 Script compiledScript = getCompiledScript(script, classLoaders);
060
061 Binding binding = new Binding(inputObjects);
062
063 compiledScript.setBinding(binding);
064
065 compiledScript.run();
066
067 if (outputNames == null) {
068 return null;
069 }
070
071 Map<String, Object> outputObjects = new HashMap<String, Object>();
072
073 for (String outputName : outputNames) {
074 outputObjects.put(outputName, binding.getVariable(outputName));
075 }
076
077 return outputObjects;
078 }
079
080 @Override
081 public String getLanguage() {
082 return _LANGUAGE;
083 }
084
085 protected Script getCompiledScript(
086 String script, ClassLoader[] classLoaders) {
087
088 GroovyShell groovyShell = getGroovyShell(classLoaders);
089
090 String key = String.valueOf(script.hashCode());
091
092 Script compiledScript = _portalCache.get(key);
093
094 if (compiledScript == null) {
095 compiledScript = groovyShell.parse(script);
096
097 _portalCache.put(key, compiledScript);
098 }
099
100 return compiledScript;
101 }
102
103 protected GroovyShell getGroovyShell(ClassLoader[] classLoaders) {
104 if (ArrayUtil.isEmpty(classLoaders)) {
105 if (_groovyShell == null) {
106 synchronized (this) {
107 if (_groovyShell == null) {
108 _groovyShell = new GroovyShell();
109 }
110 }
111 }
112
113 return _groovyShell;
114 }
115
116 ClassLoader aggregateClassLoader =
117 AggregateClassLoader.getAggregateClassLoader(
118 ClassLoaderUtil.getPortalClassLoader(), classLoaders);
119
120 GroovyShell groovyShell = _groovyShells.get(aggregateClassLoader);
121
122 if (groovyShell == null) {
123 groovyShell = new GroovyShell(aggregateClassLoader);
124
125 GroovyShell oldGroovyShell = _groovyShells.putIfAbsent(
126 aggregateClassLoader, groovyShell);
127
128 if (oldGroovyShell != null) {
129 groovyShell = oldGroovyShell;
130 }
131 }
132
133 return groovyShell;
134 }
135
136 private static final String _CACHE_NAME = GroovyExecutor.class.getName();
137
138 private static final String _LANGUAGE = "groovy";
139
140 private volatile GroovyShell _groovyShell = new GroovyShell();
141 private final ConcurrentMap<ClassLoader, GroovyShell> _groovyShells =
142 new ConcurrentReferenceKeyHashMap<ClassLoader, GroovyShell>(
143 FinalizeManager.WEAK_REFERENCE_FACTORY);
144 private final PortalCache<String, Script> _portalCache =
145 SingleVMPoolUtil.getCache(_CACHE_NAME);
146
147 }