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 2009/02/02 13:22:21 UTC
svn commit: r739973 [3/3] - in /incubator/sling/trunk/scripting/scala: ./
engine/ engine/src/ engine/src/main/ engine/src/main/java/
engine/src/main/java/org/ engine/src/main/java/org/apache/
engine/src/main/java/org/apache/sling/ engine/src/main/java/...
Added: incubator/sling/trunk/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala?rev=739973&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala (added)
+++ incubator/sling/trunk/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/ScalaInterpreter.scala Mon Feb 2 12:22:19 2009
@@ -0,0 +1,368 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import scala.tools.nsc.{Settings, Global}
+import scala.tools.nsc.interpreter.AbstractFileClassLoader
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.reporters.Reporter
+import scala.tools.nsc.util.{SourceFile, BatchSourceFile}
+import java.net.URLClassLoader
+import java.io.{File, InputStream, OutputStream}
+import org.apache.sling.scripting.scala.Utils.{option}
+
+package org.apache.sling.scripting.scala.interpreter {
+
+/**
+ * An interpreter for Scala scripts. Interpretation of scripts proceeds in the following steps:
+ * <ol>
+ * <li>Pre-compilation: The source script is {@link #preProcess} wrapped into an object wrapper which
+ * contains variable definitions of the approproate types for the passed {@link Bindings bindings}.</li>
+ * <li>Compilation: The resulting source code is {@link #compile compiled} by the Scala compiler. </li>
+ * <li>Execution: The class file is {@link #execute loaded} and its main method called.</li>
+ * </ol>
+ * @param settings compiler settings
+ * @param reporter reporter for compilation
+ * @param classes additional classes for the classpath
+ * @param outDir ourput directory for the compiler
+ */
+class ScalaInterpreter(settings: Settings, reporter: Reporter, classes: Array[AbstractFile],
+ outDir: AbstractFile) {
+
+ /**
+ * Same as <code>ScalaInterpreter(settings, reporter, classes, null)</code>.
+ * @param settings
+ * @param reporter
+ * @param classes
+ * @return
+ */
+ def this(settings: Settings, reporter: Reporter, classes: Array[AbstractFile]) =
+ this(settings, reporter, classes, null)
+
+ /**
+ * Same as <code>ScalaInterpreter(settings, reporter, null, outDir)</code>.
+ * @param settings
+ * @param reporter
+ * @param outDir
+ * @return
+ */
+ def this(settings: Settings, reporter: Reporter, outDir: AbstractFile) =
+ this(settings, reporter, null, outDir)
+
+ /**
+ * Same as <code>ScalaInterpreter(settings, reporter, null, null)</code>.
+ * @param settings
+ * @param reporter
+ * @return
+ */
+ def this(settings: Settings, reporter: Reporter) =
+ this(settings, reporter, null, null)
+
+ /**
+ * Line separater used in the wrapper object
+ */
+ protected val NL: String = System.getProperty("line.separator");
+
+ /**
+ * The parent class loader used for execution
+ */
+ protected val parentClassLoader: ClassLoader = getClass.getClassLoader
+
+ /**
+ * The Scala compiler used for compilation
+ */
+ protected val compiler: Global = {
+ val c = new ScalaCompiler(settings, reporter, classes)
+ if (outDir != null) c.genJVM.outputDir = outDir
+ c
+ }
+
+ /**
+ * Utility method for parsing a fully quallyfied class name into its packet compounds
+ * @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
+
+ /**
+ * Pre processor for wrapping the script such that it becomes a valid Scala source entity
+ * which can be passed the the Scala compiler.
+ * @param name name of the script. Used for generating the class name of the wrapper.
+ * @param code source code of the script
+ * @param bindings bindings to be passed to the script
+ * @return a valid Scala source
+ */
+ protected def preProcess(name: String, code: String, bindings: Bindings): String = {
+ def bind(a: (String, Argument[_])) =
+ "val " + a._1 + " = bindings.getValue(\"" + a._1 + "\").asInstanceOf[" + a._2.getType.getName + "]"
+
+ val compounds = packetize(name)
+
+ def packageDeclaration =
+ if (compounds.size > 1) compounds.init.mkString("package ", ".", "") + NL
+ else ""
+
+ def className = compounds.last
+
+ packageDeclaration +
+ "object " + className + " {" + NL +
+ " def main(bindings: org.apache.sling.scripting.scala.interpreter.Bindings," + NL +
+ " stdIn: java.io.InputStream," + NL +
+ " stdOut: java.io.OutputStream) {" + NL +
+ " def run() {" + NL +
+ bindings.map(bind).mkString("", NL, NL) +
+ code + "" + NL +
+ " return" + NL +
+ " }" + NL +
+ " Console.withIn(stdIn) {" + NL +
+ " Console.withOut(stdOut) {" + NL +
+ " run" + NL +
+ " stdOut.flush" + NL +
+ " }" + NL +
+ " }" + NL +
+ " }" + NL +
+ "}" + NL
+ }
+
+ /**
+ * Compiles a list of source files. No pre-processing takes place.
+ * @param sources source files
+ * @return result of compilation
+ */
+ protected def compile(sources: List[SourceFile]): Reporter = {
+ reporter.reset
+ val run = new compiler.Run
+ if (reporter.hasErrors)
+ reporter
+ else {
+ run.compileSources(sources)
+ reporter
+ }
+ }
+
+ /**
+ * Compiles a single source file. No pre-processing takes place.
+ * @param name name of the script
+ * @param code source code
+ * @return result of compilation
+ */
+ def compile(name: String, code: String): Reporter =
+ compile(List(new BatchSourceFile(name, code.toCharArray)))
+
+ /**
+ * Pre-processes and compiles a single source file.
+ * @param name name of the script
+ * @param code source code
+ * @param bindings variable bindings to pass to the script
+ * @return result of compilation
+ */
+ def compile(name: String, code: String, bindings: Bindings): Reporter =
+ compile(name, preProcess(name, code, bindings))
+
+ /**
+ * Compiles a single source file. No pre-processing takes place.
+ * @param sources source file
+ * @return result of compilation
+ */
+ def compile(source: AbstractFile): Reporter = {
+ compile(List(new BatchSourceFile(source)))
+ }
+
+ /**
+ * Pre-processes and compiles a single source file.
+ * @param name name of the script
+ * @param source source file
+ * @param bindings variable bindings to pass to the script
+ * @return result of compilation
+ */
+ def compile(name: String, source: AbstractFile, bindings: Bindings): Reporter = {
+ val code = new String(source.toByteArray)
+ compile(name, preProcess(name, code, bindings))
+ }
+
+ /**
+ * Interprete a script
+ * @param name name of the script
+ * @param code source code
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, code: String, bindings: Bindings, in: Option[InputStream],
+ out: Option[OutputStream]): Reporter = {
+ compile(name, code, bindings)
+ if (reporter.hasErrors)
+ reporter
+ else {
+ execute(name, bindings, in, out)
+ }
+ }
+
+ /**
+ * Same as <code>interprete(name, code, bindings, None, None)</code>.
+ * @param name name of the script
+ * @param code source code
+ * @param bindings variable bindings to pass to the script
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, code: String, bindings: Bindings): Reporter =
+ interprete(name, code, bindings, None, None)
+
+ /**
+ * Same as <code>interprete(name, code, bindings, Some(in), Some(out))</code>.
+ * @param name name of the script
+ * @param code source code
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, code: String, bindings: Bindings, in: InputStream,
+ out: OutputStream): Reporter =
+ interprete(name, code, bindings, option(in), option(out))
+
+ /**
+ * Interprete a script
+ * @param name name of the script
+ * @param source source file
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, source: AbstractFile, bindings: Bindings, in: Option[InputStream],
+ out: Option[OutputStream]): Reporter = {
+ compile(name, source, bindings)
+ if (reporter.hasErrors)
+ reporter
+ else {
+ execute(name, bindings, in, out)
+ }
+ }
+
+ /**
+ * Same as <code>interprete(name, code, bindings, None, None)</code>.
+ * @param name name of the script
+ * @param source source file
+ * @param bindings variable bindings to pass to the script
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, source: AbstractFile, bindings: Bindings): Reporter =
+ interprete(name, source, bindings, None, None)
+
+ /**
+ * Same as <code>interprete(name, code, bindings, Some(in), Some(out))</code>.
+ * @param name name of the script
+ * @param source source file
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException
+ */
+ @throws(classOf[InterpreterException])
+ def interprete(name: String, source: AbstractFile, bindings: Bindings, in: InputStream,
+ out: OutputStream): Reporter =
+ interprete(name, source, bindings, option(in), option(out))
+
+ /**
+ * Looks up the class file for a compiled script
+ * @param name script name
+ * @return the class file or null if not found
+ */
+ def getClassFile(name: String): AbstractFile = {
+ var file: AbstractFile = compiler.genJVM.outputDir
+ val pathParts = name.split("[./]").toList
+ for (dirPart <- pathParts.init) {
+ file = file.lookupName(dirPart, true)
+ if (file == null) {
+ return null
+ }
+ }
+ file.lookupName(pathParts.last + ".class", false)
+ }
+
+ /**
+ * Executes a compiled script
+ * @param name name of the script
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException when class files cannot be accessed or nor entry point is found
+ */
+ @throws(classOf[InterpreterException])
+ def execute(name: String, bindings: Bindings, in: Option[InputStream], out: Option[OutputStream]): Reporter = {
+ try {
+ val classLoader = new AbstractFileClassLoader(compiler.genJVM.outputDir, parentClassLoader)
+ val script = Class.forName(name, true, classLoader)
+ val initMethod = (script
+ .getDeclaredMethods
+ .toList
+ .find(method => method.getName == "main")
+ .get)
+
+ initMethod.invoke(null, Array(bindings, in.getOrElse(java.lang.System.in),
+ out.getOrElse(java.lang.System.out)): _*)
+ reporter
+ }
+ catch {
+ case e: java.lang.reflect.InvocationTargetException =>
+ throw new InterpreterException("Error executing " + name, e.getTargetException)
+ case e: Exception =>
+ throw new InterpreterException("Error executing " + name, e)
+ }
+ }
+
+ /**
+ * Same as <code>execute(name, bindings, None, None)</code>.
+ * @param name name of the script
+ * @param bindings variable bindings to pass to the script
+ * @return result of execution
+ * @throws InterpreterException when class files cannot be accessed or nor entry point is found
+ */
+ @throws(classOf[InterpreterException])
+ def execute(name: String, bindings: Bindings): Reporter =
+ execute(name, bindings, None, None)
+
+ /**
+ * Same as <code>execute(name, bindings, Some(in), Some(out))</code>.
+ * @param name name of the script
+ * @param bindings variable bindings to pass to the script
+ * @param in stdIn for the script execution
+ * @param out stdOut for the script execution
+ * @return result of execution
+ * @throws InterpreterException when class files cannot be accessed or nor entry point is found
+ */
+ @throws(classOf[InterpreterException])
+ def execute(name: String, bindings: Bindings, in: InputStream, out: OutputStream): Reporter =
+ execute(name, bindings, option(in), option(out))
+
+}
+
+
+}
\ No newline at end of file
Added: incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala?rev=739973&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala (added)
+++ incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/InterpreterTest.scala Mon Feb 2 12:22:19 2009
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import junit.framework.TestCase
+import junit.framework.Assert.{assertEquals, assertFalse}
+import scala.tools.nsc.Settings
+import scala.tools.nsc.io.VirtualDirectory
+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.jackrabbit.core.{TransientRepository}
+
+package org.apache.sling.scripting.scala.interpreter {
+
+class InterpreterTest extends TestCase {
+ var session: Session = null
+ var repository: Repository = null
+ var testRoot: Node = null
+
+ override def setUp() {
+ super.setUp()
+ repository = new TransientRepository
+ session = repository.login(new SimpleCredentials("admin", "admin".toCharArray))
+ testRoot = session.getRootNode.addNode("testRoot", "nt:folder")
+ session.save()
+ }
+
+ override def tearDown() {
+ testRoot.remove()
+ testRoot = null
+ session.save()
+ session.logout()
+ session = null
+ repository = null
+ super.tearDown()
+ }
+
+ private def reporter(settings: Settings) =
+ new ConsoleReporter(settings, null, new java.io.PrintWriter(Console.err))
+
+ private def classpath = {
+ valueOrElse(System.getProperty("surefire.test.class.path")) {
+ System.getProperty("java.class.path")
+ }
+ }
+
+ private def settings = {
+ val s = new Settings
+ s.classpath.value = classpath
+ s
+ }
+
+ def testScalaInterpreter {
+ val outdir = new VirtualDirectory("outdir", None)
+ val interpreter = new ScalaInterpreter(settings, reporter(settings), outdir)
+
+ val bindings = new ScalaBindings
+ val time = java.util.Calendar.getInstance.getTime
+ bindings.put("msg", "Hello world", classOf[String])
+ bindings.put("time", time, classOf[java.util.Date])
+
+ val code = "print(msg + \": \" + time)"
+
+ // todo fix: uncomment when trac-1618 is fixed
+ for (name <- /*"org.apache.sling.scripting.scala.interpreter.Testi"::*/"Testi"::Nil) {
+ val out = new java.io.ByteArrayOutputStream
+ val result = interpreter.interprete(name, code, bindings, None, Some(out))
+ assertFalse(result.hasErrors)
+ assertEquals("Hello world: " + time, out.toString)
+ }
+ }
+
+ def testScalaInterpreterWithJcr {
+ val appNode = testRoot.addNode("app", "nt:folder")
+ testRoot.save()
+
+ val appDir = JcrFS.create(appNode)
+ val outDir = appDir.subdirectoryNamed("outdir")
+ val srcDir = appDir.subdirectoryNamed("srcdir")
+ val interpreter = new ScalaInterpreter(settings, reporter(settings), outDir)
+
+ val bindings = new ScalaBindings
+ val time = java.util.Calendar.getInstance.getTime
+ bindings.put("msg", "Hello world", classOf[String])
+ bindings.put("time", time, classOf[java.util.Date])
+
+ val src = srcDir.fileNamed("Testi")
+ val writer = new PrintWriter(src.output)
+ writer.print("print(msg + \": \" + time)")
+ writer.close
+
+ for (name <- "org.apache.sling.scripting.scala.interpreter.Testi"::"Testi"::Nil) {
+ val out = new java.io.ByteArrayOutputStream
+ val result = interpreter.interprete(name, src, bindings, None, Some(out))
+ assertFalse(result.hasErrors)
+ assertEquals("Hello world: " + time, out.toString)
+ }
+ }
+
+ def testCompileExecute {
+ val appNode = testRoot.addNode("app", "nt:folder")
+ testRoot.save()
+
+ val appDir = JcrFS.create(appNode)
+ val outDir = appDir.subdirectoryNamed("outdir")
+ val srcDir = appDir.subdirectoryNamed("srcdir")
+ val interpreter = new ScalaInterpreter(settings, reporter(settings), outDir)
+
+ val bindings = new ScalaBindings
+ val time = java.util.Calendar.getInstance.getTime
+ bindings.put("msg", "Hello world", classOf[String])
+ bindings.put("time", time, classOf[java.util.Date])
+
+ val src = srcDir.fileNamed("Testi")
+ val writer = new PrintWriter(src.output)
+ writer.print("print(msg + \": \" + time)")
+ writer.close
+
+ for (name <- "org.apache.sling.scripting.scala.interpreter.Testi"::"Testi"::Nil) {
+ val out = new java.io.ByteArrayOutputStream
+ var result = interpreter.compile(name, src, bindings)
+ assertFalse(result.hasErrors)
+
+ result = interpreter.execute(name, bindings, None, Some(out))
+ assertFalse(result.hasErrors)
+
+ assertEquals("Hello world: " + time, out.toString)
+ }
+ }
+
+}
+
+}
\ No newline at end of file
Added: incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/JcrFSTest.scala
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/JcrFSTest.scala?rev=739973&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/JcrFSTest.scala (added)
+++ incubator/sling/trunk/scripting/scala/interpreter/src/test/scala/org/apache/sling/scripting/scala/interpreter/JcrFSTest.scala Mon Feb 2 12:22:19 2009
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.{PrintWriter, InputStreamReader}
+import javax.jcr.{Session, Repository, Node, SimpleCredentials}
+import junit.framework.TestCase
+import junit.framework.Assert.{assertEquals, assertTrue, assertFalse}
+import org.apache.sling.scripting.scala.interpreter.JcrFS.{JcrNode, JcrFile, JcrFolder}
+import org.apache.jackrabbit.core.{TransientRepository}
+
+package org.apache.sling.scripting.scala.interpreter {
+
+class JcrFSTest extends TestCase {
+ var session: Session = null
+ var repository: Repository = null
+ var testRoot: Node = null
+
+ override def setUp() {
+ super.setUp()
+ repository = new TransientRepository
+ session = repository.login(new SimpleCredentials("admin", "admin".toCharArray))
+ testRoot = session.getRootNode.addNode("testRoot", "nt:folder")
+ session.save()
+ }
+
+ override def tearDown() {
+ testRoot.remove()
+ testRoot = null
+ session.save()
+ session.logout()
+ session = null
+ repository = null
+ super.tearDown()
+ }
+
+ def testTraverse: Unit = {
+ def traverse(entry: JcrNode): String = {
+ (for (entry <- entry.elements) yield {entry match {
+ case file: JcrFile => file.path
+ case folder: JcrFolder => folder.path + traverse(folder)
+ }})
+ .mkString("(", ",", ")")
+ }
+
+ var _id = 0
+ def id() = {
+ _id += 1
+ _id
+ }
+
+ def addChildren(folder: Node) = {
+ folder.addNode("file" + id(), "nt:file")
+ folder.addNode("file" + id(), "nt:file")
+ (folder.addNode("folder" + id(), "nt:folder"), folder.addNode("folder" + id(), "nt:folder"))
+ }
+
+ val (f1, f2) = addChildren(testRoot)
+ val (f3, f4) = addChildren(f1)
+ addChildren(f2)
+ addChildren(f3)
+ addChildren(f4)
+ val actual = traverse(JcrFS.create(testRoot))
+ val expected =
+ "(/testRoot/file1,/testRoot/file2,/testRoot/folder3(/testRoot/folder3/file5,/testRoot/folder3/file6," +
+ "/testRoot/folder3/folder7(/testRoot/folder3/folder7/file13,/testRoot/folder3/folder7/file14," +
+ "/testRoot/folder3/folder7/folder15(),/testRoot/folder3/folder7/folder16())," +
+ "/testRoot/folder3/folder8(/testRoot/folder3/folder8/file17,/testRoot/folder3/folder8/file18," +
+ "/testRoot/folder3/folder8/folder19(),/testRoot/folder3/folder8/folder20()))," +
+ "/testRoot/folder4(/testRoot/folder4/file9,/testRoot/folder4/file10,/testRoot/folder4/folder11()," +
+ "/testRoot/folder4/folder12()))"
+ assertEquals(expected, actual)
+ }
+
+ def testCreateFile {
+ val root = JcrFS.create(testRoot)
+ val file = root.fileNamed("file")
+ val fileNode = testRoot.getNode("file")
+ assertFalse(file.isDirectory)
+ assertEquals("nt:file", fileNode.getPrimaryNodeType.getName)
+ assertEquals("file", file.name)
+ assertEquals("/testRoot/file", file.path)
+ assertEquals(fileNode.getProperty("jcr:content/jcr:lastModified").getLong, file.lastModified)
+ assertEquals(fileNode.getProperty("jcr:content/jcr:data").getLength, file.sizeOption.get.toLong)
+
+ val contentNode = fileNode.getNode("jcr:content")
+ assertEquals("nt:resource", contentNode.getPrimaryNodeType.getName)
+
+ val input = file.input
+ assertEquals(0, input.available)
+ assertEquals(-1, input.read)
+ }
+
+ def testCreateFolder {
+ val root = JcrFS.create(testRoot)
+ val folder = root.subdirectoryNamed("folder")
+ val folderNode = testRoot.getNode("folder")
+ assertTrue(folder.isDirectory)
+ assertEquals(0L, folder.lastModified)
+ assertEquals("nt:folder", folderNode.getPrimaryNodeType.getName)
+ assertEquals("folder", folder.name)
+ assertEquals("/testRoot/folder", folder.path)
+ }
+
+ def testParent {
+ val root = JcrFS.create(testRoot)
+ val folder = root.subdirectoryNamed("folder")
+ val file = folder.fileNamed("file")
+ assertEquals(folder, file.container)
+ }
+
+ def testReadWriteContent {
+ val root = JcrFS.create(testRoot)
+ val file = root.fileNamed("file")
+ val contentNode = testRoot.getNode("file/jcr:content")
+
+ val writer = new PrintWriter(file.output)
+ writer.print("Hello world")
+ writer.close
+ assertEquals("Hello world", contentNode.getProperty("jcr:data").getString)
+ assertEquals(11, file.sizeOption.get)
+
+ val reader = new InputStreamReader(file.input)
+ val c = new Array[char](32)
+ reader.read(c)
+ assertEquals("Hello world", new String(c, 0, 11))
+ }
+
+}
+
+}
Added: incubator/sling/trunk/scripting/scala/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/scala/pom.xml?rev=739973&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/scala/pom.xml (added)
+++ incubator/sling/trunk/scripting/scala/pom.xml Mon Feb 2 12:22:19 2009
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.scala</artifactId>
+ <packaging>pom</packaging>
+ <version>0.9.0-incubator-SNAPSHOT</version>
+ <name>Apache Sling Scala Scripting Support</name>
+ <description>Reactor project for Apache Sling Scala Scripting Support</description>
+
+ <modules>
+ <module>interpreter</module>
+ <module>engine</module>
+ </modules>
+
+</project>
Propchange: incubator/sling/trunk/scripting/scala/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native