Author: cziegeler
Date: Thu Dec 24 09:09:54 2009
New Revision: 893712

URL: http://svn.apache.org/viewvc?rev=893712&view=rev
Log:
SLING-1236 : Scala Scripting: Make all types of the script arguments visible on 
the Scala side. Apply patch from Michael Dürig

Modified:
    
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
    
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
    
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngine.java
    
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngineFactory.java
    
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaScriptEngineTest.java
    
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaTestBase.java
    
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/Bindings.scala
    
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala
    
sling/trunk/contrib/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala
    
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/html.scala
    
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/search.scala
    
sling/trunk/contrib/scripting/scala/samples/hello-world/src/main/resources/content/apps/helloworld/html.scala

Modified: 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
 (original)
+++ 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
 Thu Dec 24 09:09:54 2009
@@ -35,7 +35,6 @@
 import javax.jcr.Value;
 import javax.jcr.lock.LockException;
 
-import org.apache.jackrabbit.util.Text;
 import org.apache.sling.commons.mime.MimeTypeService;
 import org.apache.sling.engine.SlingSettingsService;
 import org.apache.sling.jcr.api.SlingRepository;
@@ -79,7 +78,7 @@
     private static final String PROP_PASSWORD_DIGEST_ALGORITHM = 
"password.digest.algorithm";
     private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
     private String passwordDigestAlgoritm = null;
-   
+
     /** default log */
     final Logger log = LoggerFactory.getLogger(getClass());
 
@@ -221,7 +220,7 @@
         try {
             StringBuffer password = new StringBuffer();
             password.append("{").append(passwordDigestAlgoritm).append("}");
-            password.append(Text.digest(passwordDigestAlgoritm,
+            
password.append(DefaultContentCreator.digest(passwordDigestAlgoritm,
                 pwd.getBytes("UTF-8")));
             return password.toString();
         } catch (NoSuchAlgorithmException e) {
@@ -230,7 +229,7 @@
             throw new IllegalArgumentException(e.toString());
         }
     }
-   
+
     // ---------- SCR Integration ---------------------------------------------
 
     /** Activates this component, called by SCR before registering as a 
service */
@@ -247,7 +246,7 @@
         } else {
             passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
         }
-       
+
         Session session = null;
         try {
             session = this.getSession();

Modified: 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
 (original)
+++ 
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
 Thu Dec 24 09:09:54 2009
@@ -20,6 +20,7 @@
 
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.text.ParseException;
@@ -57,7 +58,6 @@
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.util.Text;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 
 /**
@@ -780,7 +780,7 @@
         */
        protected String hashPath(String item) throws RepositoryException {
                try {
-                       String hash = Text.digest("sha1", INSTANCE_SEED + item, 
"UTF-8");
+                       String hash = digest("sha1", (INSTANCE_SEED + 
item).getBytes("UTF-8"));
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < STORAGE_LEVELS; i++) {
                                sb.append(hash, i * 2, (i * 2) + 2).append("/");
@@ -906,4 +906,33 @@
 
                accessControlManager.setPolicy(resourcePath, updatedAcl);
        }
+
+       /**
+     * used for the md5
+     */
+    private static final char[] hexTable = "0123456789abcdef".toCharArray();
+
+    /**
+     * Digest the plain string using the given algorithm.
+     *
+     * @param algorithm The alogrithm for the digest. This algorithm must be
+     *                  supported by the MessageDigest class.
+     * @param data      the data to digest with the given algorithm
+     * @return The digested plain text String represented as Hex digits.
+     * @throws java.security.NoSuchAlgorithmException if the desired algorithm 
is not supported by
+     *                                  the MessageDigest class.
+     */
+    public static String digest(String algorithm, byte[] data)
+            throws NoSuchAlgorithmException {
+
+        MessageDigest md = MessageDigest.getInstance(algorithm);
+        byte[] digest = md.digest(data);
+        StringBuffer res = new StringBuffer(digest.length * 2);
+        for (int i = 0; i < digest.length; i++) {
+            byte b = digest[i];
+            res.append(hexTable[(b >> 4) & 15]);
+            res.append(hexTable[b & 15]);
+        }
+        return res.toString();
+    }
 }

Modified: 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngine.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngine.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngine.java
 (original)
+++ 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngine.java
 Thu Dec 24 09:09:54 2009
@@ -21,10 +21,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.Writer;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -36,15 +34,14 @@
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptException;
 
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.scripting.SlingBindings;
 import org.apache.sling.api.scripting.SlingScript;
 import org.apache.sling.api.scripting.SlingScriptHelper;
 import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
+import org.apache.sling.scripting.scala.interpreter.Bindings;
+import org.apache.sling.scripting.scala.interpreter.Bindings$;
 import org.apache.sling.scripting.scala.interpreter.JcrFS;
-import org.apache.sling.scripting.scala.interpreter.ScalaBindings;
 import org.apache.sling.scripting.scala.interpreter.ScalaInterpreter;
 import org.apache.sling.scripting.scala.interpreter.JcrFS.JcrNode;
 import org.slf4j.Logger;
@@ -74,8 +71,7 @@
                 throw new IllegalArgumentException("Bindings does not contain 
script helper object");
             }
 
-            TypeHints typeHints = new TypeHints(bindings);
-            final ScalaBindings scalaBindings = new ScalaBindings();
+            final Bindings scalaBindings = Bindings$.MODULE$.apply();
             for (String name : bindings.keySet()) {
                 if (name == null) {
                     log.debug("Bindings contain null key. skipping");
@@ -87,40 +83,28 @@
                     log.debug("{} has null value. skipping", name);
                     continue;
                 }
-                Class<?> typeHint = typeHints.getType(name);
-                if (typeHint == null) {
-                    log.debug("{} has no type hint. skipping");
-                    continue;
-                }
 
-                scalaBindings.put(makeIdentifier(name), value, typeHint);
+                scalaBindings.putValue(makeIdentifier(name), value);
             }
 
             final JcrNode script = getScriptSource(scriptHelper);
             final long scriptMod = script.lastModified();
             final String scriptName = getScriptName(scriptHelper);
 
-            Boolean outDated = readLocked(new Callable<Boolean>() {
-                public Boolean call() throws Exception {
-                    return isOutDated(scriptMod, scriptName);
+            // xxx: Scripts need to be compiled everytime.
+            // The preamble for injecting the bindings into the script
+            // dependes on the actual types of the bindings. So effectively
+            // there is a specific script generated for each type of bindings.
+            Reporter result = writeLocked(new Callable<Reporter>() {
+                public Reporter call() throws Exception {
+                    return interpreter.compile(scriptName, script, 
scalaBindings);
                 }
             });
-
-            if (outDated) {
-                Reporter result = writeLocked(new Callable<Reporter>() {
-                    public Reporter call() throws Exception {
-                        return isOutDated(scriptMod, scriptName)
-                            ? interpreter.compile(scriptName, script, 
scalaBindings)
-                            : null;
-                    }
-                });
-
-                if (result != null && result.hasErrors()) {
-                    throw new ScriptException(result.toString());
-                }
+            if (result != null && result.hasErrors()) {
+                throw new ScriptException(result.toString());
             }
 
-            Reporter result = readLocked(new Callable<Reporter>() {
+            result = readLocked(new Callable<Reporter>() {
                 public Reporter call() throws Exception {
                     OutputStream outputStream = getOutputStream(context);
                     Reporter result = interpreter.execute(scriptName, 
scalaBindings, getInputStream(context),
@@ -331,68 +315,6 @@
         };
     }
 
-    @SuppressWarnings("serial")
-    private static class TypeHints extends HashMap<String, Class<?>> {
-        public static final Class<SlingHttpServletRequest> REQUEST_TYPE = 
SlingHttpServletRequest.class;
-        public static final Class<SlingHttpServletResponse> RESPONSE_TYPE = 
SlingHttpServletResponse.class;
-        public static final Class<Reader> READER_TYPE = Reader.class;
-        public static final Class<SlingScriptHelper> SLING_TYPE = 
SlingScriptHelper.class;
-        public static final Class<Resource> RESOURCE_TYPE = Resource.class;
-        public static final Class<PrintWriter> OUT_TYPE = PrintWriter.class;
-        public static final Class<Boolean> FLUSH_TYPE = Boolean.class;
-        public static final Class<Logger> LOG_TYPE = Logger.class;
-        public static final Class<Node> NODE_TYPE = Node.class;
-
-        private static final java.util.Map<String, Class<?>> TYPES = new 
HashMap<String, Class<?>>() {{
-            put(SlingBindings.REQUEST, REQUEST_TYPE);
-            put(SlingBindings.RESPONSE, RESPONSE_TYPE);
-            put(SlingBindings.READER, READER_TYPE);
-            put(SlingBindings.SLING, SLING_TYPE);
-            put(SlingBindings.RESOURCE, RESOURCE_TYPE);
-            put(SlingBindings.OUT, OUT_TYPE);
-            put(SlingBindings.FLUSH, FLUSH_TYPE);
-            put(SlingBindings.LOG, LOG_TYPE);
-            put("currentNode", NODE_TYPE);
-        }};
-
-        public TypeHints(SlingBindings bindings) {
-            super();
-            for (Object name : bindings.keySet()) {
-                setType((String) name, TYPES.get(name));
-            }
-        }
-
-        public void setType(String name, Class<?> type) {
-            if (type != null) {
-                put(name, type);
-            }
-        }
-
-        public Class<?> getType(String name) {
-            Class<?> c = get(name);
-            return c == null ? Object.class : c;
-        }
-
-        /**
-         * Compile time assertion enforcing type safety
-         */
-        @SuppressWarnings("unused")
-        private static class CompileTimeAssertion {
-            static {
-                SlingBindings b = new SlingBindings();
-                b.setRequest(REQUEST_TYPE.cast(null));
-                b.setResponse(RESPONSE_TYPE.cast(null));
-                b.setReader(READER_TYPE.cast(null));
-                b.setSling(SLING_TYPE.cast(null));
-                b.setResource(RESOURCE_TYPE.cast(null));
-                b.setOut(OUT_TYPE.cast(null));
-                b.setFlush(FLUSH_TYPE.cast(null));
-                b.setLog(LOG_TYPE.cast(null));
-            }
-        }
-
-    }
-
 }
 
 

Modified: 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngineFactory.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngineFactory.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngineFactory.java
 (original)
+++ 
sling/trunk/contrib/scripting/scala/engine/src/main/java/org/apache/sling/scripting/scala/engine/ScalaScriptEngineFactory.java
 Thu Dec 24 09:09:54 2009
@@ -42,6 +42,7 @@
 import org.apache.sling.scripting.scala.interpreter.ScalaInterpreter;
 import org.osgi.framework.Bundle;
 import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import scala.tools.nsc.Settings;
@@ -56,6 +57,8 @@
  * @scr.service
  */
 public class ScalaScriptEngineFactory extends AbstractScriptEngineFactory {
+    private static final Logger log = 
LoggerFactory.getLogger(ScalaScriptEngineFactory.class);
+
     private static final String PATH_SEPARATOR = 
System.getProperty("path.separator");
 
     public final static String[] SCALA_SCRIPT_EXTENSIONS = {"scala", "scs"};
@@ -164,7 +167,7 @@
                 url = bundles[k].getResource("");
             }
 
-            if (url != null) { // FIXME: log null values
+            if (url != null) {
                 if ("file".equals(url.getProtocol())) {
                     try {
                         bundleFs[k] = new PlainFile(new File(url.toURI()));
@@ -177,6 +180,9 @@
                     bundleFs[k] = BundleFS.create(bundles[k]);
                 }
             }
+            else {
+                log.warn("Cannot retreive resources from Bundle {}. 
Skipping.", bundles[k].getSymbolicName());
+            }
         }
         return bundleFs;
     }

Modified: 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaScriptEngineTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaScriptEngineTest.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaScriptEngineTest.java
 (original)
+++ 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaScriptEngineTest.java
 Thu Dec 24 09:09:54 2009
@@ -28,9 +28,10 @@
 import javax.naming.NamingException;
 import javax.script.ScriptException;
 
+import org.apache.sling.scripting.scala.interpreter.Bindings;
+import org.apache.sling.scripting.scala.interpreter.Bindings$;
 import org.apache.sling.scripting.scala.interpreter.InterpreterException;
 import org.apache.sling.scripting.scala.interpreter.JcrFS;
-import org.apache.sling.scripting.scala.interpreter.ScalaBindings;
 import org.apache.sling.scripting.scala.interpreter.JcrFS.JcrNode;
 
 import scala.tools.nsc.io.AbstractFile;
@@ -74,7 +75,7 @@
     public void testDefaultPackage() {
         String code = "package a { object Testi { print(1 + 2)}}";
         try {
-            evalScala("Testi", code, new ScalaBindings());
+            evalScala("Testi", code, Bindings$.MODULE$.apply());
         }
         catch (ScriptException e) {
             Throwable cause = e.getCause();
@@ -92,8 +93,8 @@
     public void testNodeAccess() throws RepositoryException, NamingException, 
ScriptException, InvocationTargetException {
         Node n = getTestRootNode();
         String code = "package a { class Testi(vars: TestiVars) { import 
vars._; print(n.getPath)}}";
-        ScalaBindings bindings = new ScalaBindings();
-        bindings.put("n", n, Node.class);
+        Bindings bindings = Bindings$.MODULE$.apply();
+        bindings.putValue("n", n);
         assertEquals(n.getPath(), evalScala(code, bindings));
     }
 
@@ -101,10 +102,10 @@
         JcrNode appDir = JcrFS.create(getAppNode());
         AbstractFile srcDir = appDir.subdirectoryNamed("srcdir");
 
-        ScalaBindings bindings = new ScalaBindings();
+        Bindings bindings = Bindings$.MODULE$.apply();
         Date time = Calendar.getInstance().getTime();
-        bindings.put("msg", "Hello world", String.class);
-        bindings.put("time", time, Date.class);
+        bindings.putValue("msg", "Hello world");
+        bindings.putValue("time", time);
 
         AbstractFile src = srcDir.fileNamed("Testi");
         PrintWriter writer = new PrintWriter(src.output());

Modified: 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaTestBase.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaTestBase.java?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaTestBase.java
 (original)
+++ 
sling/trunk/contrib/scripting/scala/engine/src/test/java/org/apache/sling/scripting/scala/ScalaTestBase.java
 Thu Dec 24 09:09:54 2009
@@ -31,9 +31,9 @@
 import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
 import org.apache.sling.scripting.scala.engine.BacklogReporter;
 import org.apache.sling.scripting.scala.interpreter.Bindings;
+import org.apache.sling.scripting.scala.interpreter.Bindings$;
 import org.apache.sling.scripting.scala.interpreter.InterpreterException;
 import org.apache.sling.scripting.scala.interpreter.JcrFS;
-import org.apache.sling.scripting.scala.interpreter.ScalaBindings;
 import org.apache.sling.scripting.scala.interpreter.ScalaInterpreter;
 import org.apache.sling.scripting.scala.interpreter.JcrFS.JcrNode;
 
@@ -91,7 +91,7 @@
     }
 
     protected String evalScala(String code) throws ScriptException {
-        Bindings bindings = new ScalaBindings();
+        Bindings bindings = Bindings$.MODULE$.apply();
         return evalScala(createScriptName(), code, bindings);
     }
 
@@ -127,7 +127,7 @@
         return evalScala(scriptName, code, bindings);
     }
 
-    protected String evalScala(String name, AbstractFile src, ScalaBindings 
bindings) throws ScriptException {
+    protected String evalScala(String name, AbstractFile src, Bindings 
bindings) throws ScriptException {
         try {
             interpreterOut.reset();
             Reporter result = interpreter.interprete(name, src, bindings, 
null, interpreterOut);

Modified: 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/Bindings.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/Bindings.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/Bindings.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/Bindings.scala
 Thu Dec 24 09:09:54 2009
@@ -14,90 +14,96 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import scala.collection.Map
-import scala.collection.mutable.HashMap
+import scala.collection._
 
 package org.apache.sling.scripting.scala.interpreter {
 
 /**
- * An argument consists of a value and its type
+ * Bindings of names to Values
  */
-trait Argument[T <: AnyRef] {
+trait Bindings extends Map[String, AnyRef] {
 
   /**
-   * @returns  the value of this argument
-   */
-  def getValue: T
-
-  /**
-   * @returns  the type of this argument
-   */
-  def getType: Class[T]
-}
-
-/**
- * Bindings of names to {...@link Argument}s
- */
-trait Bindings extends Map[String, Argument[_]] {
-
-  /**
-   * Associate an argument with a name
+   * Associate a value with a name
    * @param name
-   * @param argument
-   * @returns  The argument which was previously associated with the
+   * @param value
+   * @returns  The value which was previously associated with the
    *   given name or null if none.
    */
-  def put(name: String, argument: Argument[_]): Argument[_]
+  def putValue(name: String, value: AnyRef): AnyRef
 
   /**
-   * Associate an argument with a name
-   * @param  name
-   * @param  value  the value of the {...@link Argument}
-   * @param  tyqe the type of the {...@link Argument}
-   */
-  def put[T <: AnyRef](name: String, value: T, tyqe: Class[T]): Argument[_] =
-    put(name, new Argument[T] {
-      def getValue: T = value
-      def getType: Class[T] = tyqe
-    })
-
-  /**
-   * @returns  the value of the {...@link Argument} associated with the given 
name
+   * @returns  the value associated with the given name
    * @param name
    */
   def getValue(name: String): AnyRef =
     get(name) match {
-      case Some(a) => a.getValue
+      case Some(a) => a
       case None => null
     }
+  
+  def getViews(clazz: Class[_]) = {
+    def findLeastAccessibleClass(clazz: Class[_]): Class[_] = {
+      if   (accessible(clazz)) clazz
+      else findLeastAccessibleClass(clazz.getSuperclass)
+    }
+    
+    def getInterfacesUpTo(clazz: Class[_], bound: Class[_]) = {
+      def getInterfacesUpTo(intfs: mutable.Set[Class[_]], clazz: Class[_], 
bound: Class[_]): mutable.Set[Class[_]] = 
+        if (clazz == bound) intfs
+        else getInterfacesUpTo(intfs ++ clazz.getInterfaces, 
clazz.getSuperclass, bound)
+      
+      getInterfacesUpTo(mutable.Set.empty, clazz, bound)
+    }
 
-  /**
-   * @returns  the type of the {...@link Argument} associated with the given 
name
-   * @param name
-   */
-  def getType(name: String): Class[_] =
-    get(name) match {
-      case Some(a) => a.getClass
-      case None => null
+    def accessible(clazz: Class[_]) = {
+      try {
+        Class.forName(clazz.getName)
+        true
+      } 
+      catch { case _ => false }
     }
+    
+    val l = findLeastAccessibleClass(clazz) 
+    var o = getInterfacesUpTo(clazz, l) 
+    var v = Set.empty ++ o
+    
+    while (!v.isEmpty) {
+      val w = v.find(_ => true).get
+      val p = w.getInterfaces.filter(accessible)
+      o = o -- p
+      v = v - w ++ p
+    }
+    
+    l::o.toList
+  } 
 }
 
 /**
- * HashMap based default implementation of {...@link Bindings}.
+ * Default implementation of {...@link Bindings} backed by a mutable Map
  */
-class ScalaBindings extends Bindings {
-  private val bindings = new HashMap[String, Argument[_]]
-
-  def size: Int = bindings.size
-  def get(name: String): Option[Argument[_]] = bindings.get(name)
-  def elements: Iterator[(String, Argument[_])] = bindings.elements
-
-  def put(name: String, argument: Argument[_]): Argument[_] =
-    bindings.put(name, argument) match {
+private class BindingsWrapper(map: mutable.Map[String, AnyRef]) extends 
Bindings {
+  def size: Int = map.size
+  def get(name: String) = map.get(name)
+  def elements: Iterator[(String, AnyRef)] = map.elements
+  
+  def putValue(name: String, value: AnyRef) = 
+    map.put(name, value) match {
       case Some(a) => a
       case None => null
     }
+  
 }
 
+object Bindings {
+  import _root_.scala.collection.jcl.Conversions.convertMap
+  
+  def apply(): Bindings = new BindingsWrapper(new mutable.HashMap)
+  def apply(map: mutable.Map[String, AnyRef]): Bindings = new 
BindingsWrapper(map)
+  def apply(map: java.util.Map[String, AnyRef]): Bindings = new 
BindingsWrapper(map)
 }
 
+}
+
+
+

Modified: 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala
 Thu Dec 24 09:09:54 2009
@@ -94,8 +94,15 @@
    * @param name  Full qualified class name
    * @return  The compounds consisting of the (sub)-packates followed by the 
class name
    */
-  protected def packetize(name: String): List[String] =
-    name.split('.').toList
+  protected def packetize(name: String): List[String] = name.split('.').toList
+  
+  /**
+   * Utility method for mangling fully quallfied class names into a valid Scala
+   * identifier. 
+   * @param name Full qualified class name
+   * @return  A valid Scala identifier
+   */
+  protected def mangle(name: String) = packetize(name).mkString("_") 
 
   /**
    * Pre processor for wrapping the script such that it becomes a valid Scala 
source entity
@@ -108,8 +115,21 @@
    */
   @throws(classOf[InterpreterException])
   protected def preProcess(name: String, code: String, bindings: Bindings): 
String = {
-    def bind(arg: (String, Argument[_])) =
-      "lazy val " + arg._1 + " = bindings.getValue(\"" + arg._1 + 
"\").asInstanceOf[" + arg._2.getType.getName + "]"
+    def bind(arg: (String, AnyRef)) = {
+      val views = bindings.getViews(arg._2.getClass)
+      val className = views.head.getName
+      val implicits = 
+        for {
+          view <- views.tail
+          intfName = view.getName
+          methName = mangle(className) + "2" + mangle(intfName)  
+        }
+        yield 
+          "    implicit def " + methName + "(x: " + className + "): " + 
intfName + " = x.asInstanceOf[" +  intfName + "]"
+      
+      "    lazy val " + arg._1 + " = bindings.getValue(\"" + arg._1 + 
"\").asInstanceOf[" + className + "]" + NL +
+      implicits.mkString(NL)
+    }
 
     val compounds = packetize(name)
 

Modified: 
sling/trunk/contrib/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala
 Thu Dec 24 09:09:54 2009
@@ -19,10 +19,11 @@
 import scala.tools.nsc.Settings
 import scala.tools.nsc.io.PlainFile
 import scala.tools.nsc.reporters.ConsoleReporter
-import org.apache.sling.scripting.scala.Utils.valueOrElse
 import java.io.PrintWriter
 import javax.jcr.{Session, Repository, Node, SimpleCredentials}
+import org.apache.sling.scripting.scala.Utils.valueOrElse
 import org.apache.jackrabbit.core.{TransientRepository}
+import org.apache.sling.scripting.scala.interpreter.Bindings
 
 package org.apache.sling.scripting.scala.interpreter {
 
@@ -69,10 +70,10 @@
     val outdir = new PlainFile(new java.io.File("."))
     val interpreter = new ScalaInterpreter(settings, reporter(settings), 
outdir)
 
-    val bindings = new ScalaBindings
+    val bindings = Bindings()
     val time = java.util.Calendar.getInstance.getTime
-    bindings.put("msg", "Hello world", classOf[String])
-    bindings.put("time", time, classOf[java.util.Date])
+    bindings.putValue("msg", "Hello world")
+    bindings.putValue("time", time)
 
     val code = "package a { class Testi(vars: TestiVars) {import vars._; 
print(msg + \": \" + time)}}"
     val name = "a.Testi"
@@ -92,10 +93,10 @@
     val srcDir = appDir.subdirectoryNamed("srcdir")
     val interpreter = new ScalaInterpreter(settings, reporter(settings), 
outDir)
 
-    val bindings = new ScalaBindings
+    val bindings = Bindings()
     val time = java.util.Calendar.getInstance.getTime
-    bindings.put("msg", "Hello world", classOf[String])
-    bindings.put("time", time, classOf[java.util.Date])
+    bindings.putValue("msg", "Hello world")
+    bindings.putValue("time", time)
 
     val code = "package a { class Testi(vars: TestiVars) {import vars._; 
print(msg + \": \" + time)}}"
     val name = "a.Testi"
@@ -120,10 +121,10 @@
     val srcDir = appDir.subdirectoryNamed("srcdir")
     val interpreter = new ScalaInterpreter(settings, reporter(settings), 
outDir)
 
-    val bindings = new ScalaBindings
+    val bindings = Bindings()
     val time = java.util.Calendar.getInstance.getTime
-    bindings.put("msg", "Hello world", classOf[String])
-    bindings.put("time", time, classOf[java.util.Date])
+    bindings.putValue("msg", "Hello world")
+    bindings.putValue("time", time)
 
     val code = "package a { class Testi(vars: TestiVars) {import vars._; 
print(msg + \": \" + time)}}"
     val name = "a.Testi"

Modified: 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/html.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/html.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/html.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/html.scala
 Thu Dec 24 09:09:54 2009
@@ -208,8 +208,11 @@
 
 class html(vars: htmlVars) {
   import java.util.Calendar
-  import vars._
+  import javax.jcr.Node
   import utils.RichJCR._
+  import vars._
+  
+  val node: Node = currentNode
     
   println {
     <html>
@@ -218,13 +221,13 @@
       </head>
       <body>
         <div id="Header">
-          Welcome to the { currentNode("name") } forum  
+          Welcome to the { node("name") } forum  
           &mdash; { Calendar.getInstance.getTime } 
         </div>
         { SearchBox.render(request) }
         <div id="Content">
           { ThreadNewForm.render }
-          { ThreadOverview.render(currentNode) }
+          { ThreadOverview.render(node) }
         </div>
       </body>
     </html>  

Modified: 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/search.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/search.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/search.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/samples/forum/src/main/resources/content/apps/forum/search.scala
 Thu Dec 24 09:09:54 2009
@@ -37,6 +37,8 @@
       <div id={ threadUUID + node.uuid + "content" }></div>
     </p></li>
   }
+  
+  val node: Node = currentNode
 
   println {
     <html>
@@ -111,7 +113,7 @@
 
        <div id="Content">
        {
-         val result = SearchBox.query(currentNode.session, request)
+         val result = SearchBox.query(node.session, request)
          <h1>search results for query { request.getParameter("qt") }, hits: { 
result.getSize() } </h1>
          <ul>
          { result map searchDetail }

Modified: 
sling/trunk/contrib/scripting/scala/samples/hello-world/src/main/resources/content/apps/helloworld/html.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/samples/hello-world/src/main/resources/content/apps/helloworld/html.scala?rev=893712&r1=893711&r2=893712&view=diff
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/samples/hello-world/src/main/resources/content/apps/helloworld/html.scala
 (original)
+++ 
sling/trunk/contrib/scripting/scala/samples/hello-world/src/main/resources/content/apps/helloworld/html.scala
 Thu Dec 24 09:09:54 2009
@@ -51,11 +51,14 @@
   
   import vars._
   
+  val node: Node = currentNode
+  
   println {
     <html>
-      <h1>{ "Hello " + currentNode("title") }</h1>
+      <h1>{ "Hello " + node("title") }</h1>
       Today is { Calendar.getInstance.getTime } <br />
-      My path is { currentNode.path } 
+      My path is { node.path } <br />
+      : { 
resource.adaptTo(classOf[javax.jcr.Node]).getProperty("title").getValue().getString()
 } <br />
       { Tree(currentNode).render }
     </html>  
   }


Reply via email to