You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/09/26 17:26:41 UTC

svn commit: r699367 - in /incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal: ./ RhinoJavaScriptEngine.java

Author: fmeschbe
Date: Fri Sep 26 08:26:40 2008
New Revision: 699367

URL: http://svn.apache.org/viewvc?rev=699367&view=rev
Log:
SLING-677 share the top level scope for the complete
request processing and move the engine to an internal
package to enable export of the SPI interfaces
(see SLING-634)

Added:
    incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/
    incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java
      - copied, changed from r688978, incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/RhinoJavaScriptEngine.java

Copied: incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java (from r688978, incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/RhinoJavaScriptEngine.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java?p2=incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java&p1=incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/RhinoJavaScriptEngine.java&r1=688978&r2=699367&rev=699367&view=diff
==============================================================================
--- incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/RhinoJavaScriptEngine.java (original)
+++ incubator/sling/trunk/scripting/javascript/src/main/java/org/apache/sling/scripting/javascript/internal/RhinoJavaScriptEngine.java Fri Sep 26 08:26:40 2008
@@ -14,9 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.scripting.javascript;
+package org.apache.sling.scripting.javascript.internal;
 
 import java.io.Reader;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.Map.Entry;
 
 import javax.script.Bindings;
@@ -30,11 +33,12 @@
 import org.apache.sling.scripting.javascript.helper.SlingWrapFactory;
 import org.apache.sling.scripting.javascript.io.EspReader;
 import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ImporterTopLevel;
 import org.mozilla.javascript.JavaScriptException;
-import org.mozilla.javascript.NativeObject;
 import org.mozilla.javascript.ScriptRuntime;
 import org.mozilla.javascript.Scriptable;
 import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.WrapFactory;
 import org.slf4j.Logger;
 
 /**
@@ -45,7 +49,8 @@
 
     private Scriptable rootScope;
 
-    public RhinoJavaScriptEngine(ScriptEngineFactory factory, Scriptable rootScope) {
+    public RhinoJavaScriptEngine(ScriptEngineFactory factory,
+            Scriptable rootScope) {
         super(factory);
         this.rootScope = rootScope;
     }
@@ -56,7 +61,7 @@
         String scriptName = "NO_SCRIPT_NAME";
         {
             SlingScriptHelper helper = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
-            if(helper != null) {
+            if (helper != null) {
                 scriptName = helper.getScript().getScriptResource().getPath();
             }
         }
@@ -66,31 +71,42 @@
             scriptReader = new EspReader(scriptReader);
         }
 
+        // container for replaced properties
+        Map<String, Object> replacedProperties = null;
+        Scriptable scope = null;
+
         // create a rhino Context and execute the script
         try {
-            
+
             final Context rhinoContext = Context.enter();
-            final ScriptableObject scope = new NativeObject();
 
-            // Set the global scope to be our prototype
-            scope.setPrototype(rootScope);
+            if (ScriptRuntime.hasTopCall(rhinoContext)) {
 
-            // We want "scope" 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 "scope".
-            scope.setParentScope(null);
+                // reuse the top scope if we are included
+                scope = ScriptRuntime.getTopCallScope(rhinoContext);
 
-            // setup the context for use
-            rhinoContext.setWrapFactory(SlingWrapFactory.INSTANCE);
+            } else {
 
-            // add initial properties to the scope
-            for (Object entryObject : bindings.entrySet()) {
-                Entry<?, ?> entry = (Entry<?, ?>) entryObject;
-                Object wrapped = ScriptRuntime.toObject(scope, entry.getValue());
-                ScriptableObject.putProperty(scope, (String) entry.getKey(),
-                    wrapped);
+                // create the request top scope, use the ImporterToplevel here
+                // to support the importPackage and importClasses functions
+                scope = new ImporterTopLevel(); // new NativeObject();
+
+                // Set the global scope to be our prototype
+                scope.setPrototype(rootScope);
+
+                // We want "scope" 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 "scope".
+                scope.setParentScope(null);
+
+                // setup the context for use
+                WrapFactory wrapFactory = ((RhinoJavaScriptEngineFactory) getFactory()).getWrapFactory();
+                rhinoContext.setWrapFactory(wrapFactory);
             }
 
+            // add initial properties to the scope
+            replacedProperties = setBoundProperties(scope, bindings);
+
             final int lineNumber = 1;
             final Object securityDomain = null;
 
@@ -98,26 +114,61 @@
                 lineNumber, securityDomain);
 
         } catch (JavaScriptException t) {
-            
+
             final ScriptException se = new ScriptException(t.details(),
                 t.sourceName(), t.lineNumber());
 
             ((Logger) bindings.get(SlingBindings.LOG)).error(t.getScriptStackTrace());
             se.setStackTrace(t.getStackTrace());
             throw se;
-            
+
         } catch (Throwable t) {
-            
-            final ScriptException se = new ScriptException("Failure running script " + scriptName
-                + ": " + t.getMessage());
+
+            final ScriptException se = new ScriptException(
+                "Failure running script " + scriptName + ": " + t.getMessage());
             se.initCause(t);
             throw se;
-            
+
         } finally {
-            
+
+            // if properties have been replaced, reset them
+            resetBoundProperties(scope, replacedProperties);
+
             Context.exit();
-            
+
+        }
+    }
+
+    private Map<String, Object> setBoundProperties(Scriptable scope,
+            Bindings bindings) {
+        Map<String, Object> replacedProperties = new HashMap<String, Object>();
+
+        for (Object entryObject : bindings.entrySet()) {
+            Entry<?, ?> entry = (Entry<?, ?>) entryObject;
+            String name = (String) entry.getKey();
+
+            // get the current property value, if set
+            if (ScriptableObject.hasProperty(scope, name)) {
+                replacedProperties.put(name, ScriptableObject.getProperty(
+                    scope, name));
+            }
+
+            // wrap the new value and set it
+            Object wrapped = ScriptRuntime.toObject(scope, entry.getValue());
+            ScriptableObject.putProperty(scope, (String) entry.getKey(),
+                wrapped);
         }
+
+        return replacedProperties;
     }
 
+    private void resetBoundProperties(Scriptable scope,
+            Map<String, Object> properties) {
+        if (scope != null && properties != null && properties.size() > 0) {
+            for (Entry<String, Object> entry : properties.entrySet()) {
+                ScriptableObject.putProperty(scope, entry.getKey(),
+                    entry.getValue());
+            }
+        }
+    }
 }