001
014
015 package com.liferay.portal.scripting.javascript;
016
017 import com.liferay.portal.kernel.cache.PortalCache;
018 import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
019 import com.liferay.portal.kernel.scripting.BaseScriptingExecutor;
020 import com.liferay.portal.kernel.scripting.ScriptingException;
021 import com.liferay.portal.kernel.util.AggregateClassLoader;
022 import com.liferay.portal.util.ClassLoaderUtil;
023
024 import java.util.HashMap;
025 import java.util.Map;
026 import java.util.Set;
027
028 import org.mozilla.javascript.Context;
029 import org.mozilla.javascript.Script;
030 import org.mozilla.javascript.Scriptable;
031 import org.mozilla.javascript.ScriptableObject;
032
033
036 public class JavaScriptExecutor extends BaseScriptingExecutor {
037
038 @Override
039 public void clearCache() {
040 _portalCache.removeAll();
041 }
042
043 @Override
044 public Map<String, Object> eval(
045 Set<String> allowedClasses, Map<String, Object> inputObjects,
046 Set<String> outputNames, String script, ClassLoader... classLoaders)
047 throws ScriptingException {
048
049 Script compiledScript = getCompiledScript(script, classLoaders);
050
051 try {
052 Context context = Context.enter();
053
054 Scriptable scriptable = context.initStandardObjects();
055
056 if ((classLoaders != null) && (classLoaders.length > 0)) {
057 ClassLoader aggregateClassLoader =
058 AggregateClassLoader.getAggregateClassLoader(
059 ClassLoaderUtil.getPortalClassLoader(), classLoaders);
060
061 context.setApplicationClassLoader(aggregateClassLoader);
062 }
063
064 for (Map.Entry<String, Object> entry : inputObjects.entrySet()) {
065 String key = entry.getKey();
066 Object value = entry.getValue();
067
068 ScriptableObject.putProperty(
069 scriptable, key, Context.javaToJS(value, scriptable));
070 }
071
072 if (allowedClasses != null) {
073 context.setClassShutter(
074 new JavaScriptClassVisibilityChecker(allowedClasses));
075 }
076
077 compiledScript.exec(context, scriptable);
078
079 if (outputNames == null) {
080 return null;
081 }
082
083 Map<String, Object> outputObjects = new HashMap<String, Object>();
084
085 for (String outputName : outputNames) {
086 outputObjects.put(
087 outputName,
088 ScriptableObject.getProperty(scriptable, outputName));
089 }
090
091 return outputObjects;
092 }
093 catch (Exception e) {
094 throw new ScriptingException(e.getMessage() + "\n\n", e);
095 }
096 finally {
097 Context.exit();
098 }
099 }
100
101 @Override
102 public String getLanguage() {
103 return _LANGUAGE;
104 }
105
106 protected Script getCompiledScript(
107 String script, ClassLoader... classLoaders) {
108
109 String key = String.valueOf(script.hashCode());
110
111 Script compiledScript = _portalCache.get(key);
112
113 if (compiledScript != null) {
114 return compiledScript;
115 }
116
117 try {
118 Context context = Context.enter();
119
120 if ((classLoaders != null) && (classLoaders.length > 0)) {
121 ClassLoader aggregateClassLoader =
122 AggregateClassLoader.getAggregateClassLoader(
123 ClassLoaderUtil.getPortalClassLoader(), classLoaders);
124
125 context.setApplicationClassLoader(aggregateClassLoader);
126 }
127
128 compiledScript = context.compileString(script, "script", 0, null);
129 }
130 finally {
131 Context.exit();
132 }
133
134 _portalCache.put(key, compiledScript);
135
136 return compiledScript;
137 }
138
139 private static final String _CACHE_NAME =
140 JavaScriptExecutor.class.getName();
141
142 private static final String _LANGUAGE = "javascript";
143
144 private PortalCache<String, Script> _portalCache =
145 SingleVMPoolUtil.getCache(_CACHE_NAME);
146
147 }