package org.apache.sling.webresource.impl; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Map; import java.util.Map.Entry; import javax.jcr.RepositoryException; import org.apache.sling.api.resource.LoginException; import org.apache.sling.webresource.WebResourceInventoryManager; import org.apache.sling.webresource.WebResourceScriptCache; import org.apache.sling.webresource.WebResourceScriptRunner; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.tools.shell.Global; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RhinoWebResourceScriptRunnerImpl implements WebResourceScriptRunner { static class SlingRhinoFactory extends ContextFactory { @Override protected boolean hasFeature(Context cx, int featureIndex) { if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) { return true; } return super.hasFeature(cx, featureIndex); } } static { ContextFactory.initGlobal(new SlingRhinoFactory()); } private Scriptable rootScope; private String scriptCompilerName; private InputStream globalScriptStream; private WebResourceInventoryManager webResourceInventoryManager; private WebResourceScriptCache webResourceScriptCache; private final Logger log = LoggerFactory.getLogger(getClass()); public RhinoWebResourceScriptRunnerImpl(String scriptCompilerName, InputStream globalScriptStream, WebResourceInventoryManager webResourceInventoryManager, WebResourceScriptCache webResourceScriptCache) { this.scriptCompilerName = scriptCompilerName; this.globalScriptStream = globalScriptStream; this.webResourceInventoryManager = webResourceInventoryManager; this.webResourceScriptCache = webResourceScriptCache; loadGlobalScripts(); } @Override public String evaluateScript(InputStream script, Map<String, Object> scriptVariables) { Context rhinoContext = getRhinoContext(); // We can share the scope. Scriptable threadScope = rhinoContext.newObject(rootScope); threadScope.setPrototype(rootScope); // We want "threadScope" to be a new top-level // scope, so set its parent scope to null. This // means that any variables created by assignments // will be properties of "threadScope". threadScope.setParentScope(null); if (scriptVariables != null) { for (Entry<String, Object> currentEntry : scriptVariables .entrySet()) { threadScope.put(currentEntry.getKey(), threadScope, Context.toObject(currentEntry.getValue(), threadScope)); } } String compiledScript = null; try { compiledScript = (String) rhinoContext.evaluateReader(threadScope, new InputStreamReader(script), "src", 1, null); } catch (IOException e) { log.error("Error compiling scripts for " + scriptCompilerName, e); } return compiledScript; } @Override public void evaluateScriptInRootConext(String scriptName, InputStream script) { Context rhinoContext = getRhinoContext(); try { rhinoContext.evaluateReader(rootScope, new InputStreamReader(script), scriptName, 1, null); } catch (IOException e) { log.error( "Error loading script " + scriptName + " to Root Context", e); } } protected void loadGlobalScripts() { Context rhinoContext = getRhinoContext(); try { rootScope = new Global(rhinoContext); rootScope .put("logger", rootScope, Context.toObject(log, rootScope)); rootScope.put("webResourceInventoryManager", rootScope, Context.toObject(webResourceInventoryManager, rootScope)); rhinoContext.evaluateReader(rootScope, new InputStreamReader( webResourceScriptCache.getGlobalWebResourceScripts()), "webResourceGlobalScript", 1, null); rhinoContext.evaluateReader(rootScope, new InputStreamReader( globalScriptStream), scriptCompilerName, 1, null); } catch (IOException e) { log.error("Error loading global scripts for " + scriptCompilerName, e); } catch (LoginException e) { log.error( "Error loading global scripts for webResourceGlobalScript", e); } catch (RepositoryException e) { log.error( "Error loading global scripts for webResourceGlobalScript", e); } } /** * * Retrieves Rhino Context and sets language and optimizations. * * @return */ public Context getRhinoContext() { Context result = null; if (Context.getCurrentContext() == null) { Context.enter(); } result = Context.getCurrentContext(); result.setOptimizationLevel(-1); result.setLanguageVersion(Context.VERSION_1_7); return result; } }