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.security.pacl.PACLClassLoaderUtil;
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 PACLClassLoaderUtil.getPortalClassLoader(),
059 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 public String getLanguage() {
102 return _LANGUAGE;
103 }
104
105 protected Script getCompiledScript(
106 String script, ClassLoader... classLoaders) {
107
108 String key = String.valueOf(script.hashCode());
109
110 Script compiledScript = _portalCache.get(key);
111
112 if (compiledScript == null) {
113 try {
114 Context context = Context.enter();
115
116 if ((classLoaders != null) && (classLoaders.length > 0)) {
117 ClassLoader aggregateClassLoader =
118 AggregateClassLoader.getAggregateClassLoader(
119 PACLClassLoaderUtil.getPortalClassLoader(),
120 classLoaders);
121
122 context.setApplicationClassLoader(aggregateClassLoader);
123 }
124
125 compiledScript = context.compileString(
126 script, "script", 0, null);
127 }
128 finally {
129 Context.exit();
130 }
131
132 _portalCache.put(key, compiledScript);
133 }
134
135 return compiledScript;
136 }
137
138 private static final String _CACHE_NAME =
139 JavaScriptExecutor.class.getName();
140
141 private static final String _LANGUAGE = "javascript";
142
143 private PortalCache<String, Script> _portalCache =
144 SingleVMPoolUtil.getCache(_CACHE_NAME);
145
146 }