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