You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2008/03/11 16:21:44 UTC

svn commit: r635972 - in /incubator/sling/trunk: api/src/main/java/org/apache/sling/api/scripting/SlingScript.java scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java

Author: cziegeler
Date: Tue Mar 11 08:21:38 2008
New Revision: 635972

URL: http://svn.apache.org/viewvc?rev=635972&view=rev
Log:
SLING-320: Allow method calls in a script; this implementation is not optimal yet, it uses the javax.script.Invocable interface if the script engine supports it; otherwise it tries to generate a javascript like method call.

Modified:
    incubator/sling/trunk/api/src/main/java/org/apache/sling/api/scripting/SlingScript.java
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java

Modified: incubator/sling/trunk/api/src/main/java/org/apache/sling/api/scripting/SlingScript.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/api/src/main/java/org/apache/sling/api/scripting/SlingScript.java?rev=635972&r1=635971&r2=635972&view=diff
==============================================================================
--- incubator/sling/trunk/api/src/main/java/org/apache/sling/api/scripting/SlingScript.java (original)
+++ incubator/sling/trunk/api/src/main/java/org/apache/sling/api/scripting/SlingScript.java Tue Mar 11 08:21:38 2008
@@ -53,4 +53,20 @@
      */
     Object eval(SlingBindings props);
 
+    /**
+     * Evaluates this script using the bound variables as global variables to
+     * the script and then calls the given method with the arguments.
+     *
+     * @param props The {@link SlingBindings} providing the bound variables for
+     *            evaluating the script. Any bound variables must conform to the
+     *            requirements of the {@link SlingBindings} predefined variables
+     *            set.
+     * @param name The name of the method to call.
+     * @param args The arguments for the method call.
+     * @return The value returned by the method from the script.
+     * @throws ScriptEvaluationException If an error occurrs executing the
+     *             script or preparing the script execution. The cause of the
+     *             evaluation execption is available as the exception cause.
+     */
+    Object call(SlingBindings props, String method, Object... args);
 }

Modified: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java?rev=635972&r1=635971&r2=635972&view=diff
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java (original)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java Tue Mar 11 08:21:38 2008
@@ -32,7 +32,9 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.Reader;
+import java.io.StringReader;
 import java.io.Writer;
+import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Hashtable;
@@ -40,6 +42,7 @@
 
 import javax.jcr.Node;
 import javax.script.Bindings;
+import javax.script.Invocable;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
@@ -100,8 +103,17 @@
      * @throws ScriptEvaluationException
      */
     public Object eval(SlingBindings props) {
+        return this.call(props, null);
+    }
 
-        String scriptName = getScriptResource().getPath();
+    // ---------- Servlet interface --------------------------------------------
+
+    /**
+     * @see org.apache.sling.api.scripting.SlingScript#call(org.apache.sling.api.scripting.SlingBindings, java.lang.String, java.lang.Object[])
+     * @throws ScriptEvaluationException
+     */
+    public Object call(SlingBindings props, String method, Object... args) {
+        final String scriptName = getScriptResource().getPath();
 
         Bindings bindings = null;
         try {
@@ -114,10 +126,21 @@
             ctx.setErrorWriter(new LogWriter((Logger) bindings.get(LOG)));
 
             Reader reader = getScriptReader();
+            if ( method != null && !(this.scriptEngine instanceof Invocable)) {
+                reader = getWrapperReader(reader, method, args);
+            }
 
             // evaluate the script
             final Object result = scriptEngine.eval(reader, ctx);
 
+            // call method - if supplied and script engine supports direct invocation
+            if ( method != null && (this.scriptEngine instanceof Invocable)) {
+                try {
+                    ((Invocable)scriptEngine).invokeFunction(method, Arrays.asList(args).toArray());
+                } catch (NoSuchMethodException e) {
+                    throw new ScriptEvaluationException(scriptName, "Method " + method + " not found in script.", e);
+                }
+            }
             // optionall flush the output channel
             Object flushObject = bindings.get(SlingBindings.FLUSH);
             if (flushObject instanceof Boolean && (Boolean) flushObject) {
@@ -146,8 +169,6 @@
         }
     }
 
-    // ---------- Servlet interface --------------------------------------------
-
     public void init(ServletConfig servletConfig) {
         if (servletConfig != null) {
             Dictionary<String, String> params = new Hashtable<String, String>();
@@ -250,6 +271,66 @@
         // converting the stream data using UTF-8 encoding, which is
         // the default encoding used
         return new BufferedReader(new InputStreamReader(input, encoding));
+    }
+
+    private Reader getWrapperReader(final Reader scriptReader, final String method, final Object... args) {
+        final StringBuffer buffer = new StringBuffer(method);
+        buffer.append('(');
+        for(Object o : args) {
+            buffer.append('"');
+            buffer.append(o);
+            buffer.append('"');
+        }
+        buffer.append(')');
+        final String msg = buffer.toString();
+        return new Reader() {
+
+            protected boolean doAppend = false;
+
+            protected StringReader methodReader = new StringReader(msg);
+            /**
+             * @see java.io.Reader#close()
+             */
+            public void close() throws IOException {
+                scriptReader.close();
+            }
+
+            @Override
+            public int read(char[] cbuf, int start, int len) throws IOException {
+                if ( doAppend ) {
+                    return methodReader.read(cbuf, start, len);
+                }
+                int readLen = scriptReader.read(cbuf, start, len);
+                if ( readLen == -1 ) {
+                    doAppend = true;
+                    return this.read(cbuf, start, len);
+                }
+                return readLen;
+            }
+
+            @Override
+            public int read() throws IOException {
+                if ( doAppend ) {
+                    return methodReader.read();
+                }
+                int value = scriptReader.read();
+                if ( value == -1 ) {
+                    doAppend = true;
+                    return methodReader.read();
+                }
+                return value;
+            }
+
+            @Override
+            public int read(char[] cbuf) throws IOException {
+                return this.read(cbuf, 0, cbuf.length);
+            }
+
+            @Override
+            public boolean ready() throws IOException {
+                return scriptReader.ready();
+            }
+        };
     }
 
     private Bindings verifySlingBindings(String scriptName,