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 public Map<String, Object> eval(
044 Set<String> allowedClasses, Map<String, Object> inputObjects,
045 Set<String> outputNames, String script, ClassLoader... classLoaders)
046 throws ScriptingException {
047
048 Script compiledScript = getCompiledScript(script, classLoaders);
049
050 try {
051 Context context = Context.enter();
052
053 Scriptable scriptable = context.initStandardObjects();
054
055 if ((classLoaders != null) && (classLoaders.length > 0)) {
056 ClassLoader aggregateClassLoader =
057 AggregateClassLoader.getAggregateClassLoader(
058 ClassLoaderUtil.getPortalClassLoader(), classLoaders);
059
060 context.setApplicationClassLoader(aggregateClassLoader);
061 }
062
063 for (Map.Entry<String, Object> entry : inputObjects.entrySet()) {
064 String key = entry.getKey();
065 Object value = entry.getValue();
066
067 ScriptableObject.putProperty(
068 scriptable, key, Context.javaToJS(value, scriptable));
069 }
070
071 if (allowedClasses != null) {
072 context.setClassShutter(
073 new JavaScriptClassVisibilityChecker(allowedClasses));
074 }
075
076 compiledScript.exec(context, scriptable);
077
078 if (outputNames == null) {
079 return null;
080 }
081
082 Map<String, Object> outputObjects = new HashMap<String, Object>();
083
084 for (String outputName : outputNames) {
085 outputObjects.put(
086 outputName,
087 ScriptableObject.getProperty(scriptable, outputName));
088 }
089
090 return outputObjects;
091 }
092 catch (Exception e) {
093 throw new ScriptingException(e.getMessage() + "\n\n", e);
094 }
095 finally {
096 Context.exit();
097 }
098 }
099
100 public String getLanguage() {
101 return _LANGUAGE;
102 }
103
104 protected Script getCompiledScript(
105 String script, ClassLoader... classLoaders) {
106
107 String key = String.valueOf(script.hashCode());
108
109 Script compiledScript = _portalCache.get(key);
110
111 if (compiledScript == null) {
112 try {
113 Context context = Context.enter();
114
115 if ((classLoaders != null) && (classLoaders.length > 0)) {
116 ClassLoader aggregateClassLoader =
117 AggregateClassLoader.getAggregateClassLoader(
118 ClassLoaderUtil.getPortalClassLoader(),
119 classLoaders);
120
121 context.setApplicationClassLoader(aggregateClassLoader);
122 }
123
124 compiledScript = context.compileString(
125 script, "script", 0, null);
126 }
127 finally {
128 Context.exit();
129 }
130
131 _portalCache.put(key, compiledScript);
132 }
133
134 return compiledScript;
135 }
136
137 private static final String _CACHE_NAME =
138 JavaScriptExecutor.class.getName();
139
140 private static final String _LANGUAGE = "javascript";
141
142 private PortalCache<String, Script> _portalCache =
143 SingleVMPoolUtil.getCache(_CACHE_NAME);
144
145 }