From f7edd5fec64f4244f13331b8c1600b8356e84df7 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Thu, 15 Mar 2012 18:53:26 +0100 Subject: [PATCH 01/29] Dedicated class for Scala source files. --- .../slang/scala/deployer/ScalaSource.scala | 42 ++++++++++++++ .../scala/deployer/ScalaTransformer.scala | 57 +++++++++++-------- .../scala/deployer/ScalaURLHandler.scala | 3 +- .../deployer/archiver/ScalaArchiver.scala | 20 ++++--- .../deployer/compiler/ScalaCompiler.scala | 20 ++++--- .../scala/deployer/ScalaTransformerTest.scala | 9 ++- 6 files changed, 104 insertions(+), 47 deletions(-) create mode 100644 scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala new file mode 100644 index 0000000..f84c13b --- /dev/null +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -0,0 +1,42 @@ +/** + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * + * Licensed 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. + */ +package org.fusesource.slang.scala.deployer + +import java.io.File +import java.net.URL +import tools.nsc.io.AbstractFile +import tools.nsc.io.PlainFile + +trait ScalaSource extends AbstractFile { + + val url : URL + + override def toString = url.toString + +} + +object ScalaSource { + + def apply (u : URL) = u.getProtocol match { + case "file" => + new PlainFile (new File (u.toURI)) with ScalaSource { val url = u } + case _ => + throw new Exception ("Protocol of a ScalaSource must be a file.") + //AbstractFile.getURL (url) with ScalaSource + } + +} diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala index 4cbef91..70c6a90 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala @@ -2,6 +2,9 @@ * Copyright (C) FuseSource, Inc. * http://fusesource.com * + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * * Licensed 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 @@ -19,24 +22,21 @@ package org.fusesource.slang.scala.deployer import archiver.ScalaArchiver import compiler.{Bundles, ScalaCompiler} import org.apache.commons.logging.LogFactory -import tools.nsc.io.{PlainFile, AbstractFile} +import tools.nsc.io.AbstractFile import java.net.URL import org.osgi.framework.{BundleContext, Bundle} -import java.io.{InputStream, File, OutputStream} +import java.io.{File, InputStream, OutputStream} -/** - * - */ class ScalaTransformer(val bundles: List[AbstractFile]) { final val LOG = LogFactory.getLog(classOf[ScalaTransformer]) - val compiler = new ScalaCompiler(bundles) + val compiler = new ScalaCompiler (bundles) - val archiver = new ScalaArchiver(bundles) + val archiver = new ScalaArchiver (bundles) - def transform(url: URL, stream: OutputStream) : Unit = { - val result = transform(url) + def transform(source: ScalaSource, stream: OutputStream) { + val result = transform(source) val bytes = new Array[Byte](1024) var read = result.read(bytes) while (read > 0) { @@ -46,25 +46,25 @@ class ScalaTransformer(val bundles: List[AbstractFile]) { result.close } - def transform(url: URL) : InputStream = { - LOG.info("Transforming " + url + " into an OSGi bundle") - archiver.archive(compile(url), url) + def transform (source: ScalaSource) : InputStream = { + LOG.info("Transforming " + source + " into an OSGi bundle") + archiver.archive(compile(source), source) } - def compile(url: URL) = compiler.compile(files(url)) - - def files(url: URL) : List[AbstractFile] = { - if ("file" == url.getProtocol) { - List(new PlainFile(new File(url.toURI))) - } else { - List(AbstractFile.getURL(url)) - } - } + def compile (source: AbstractFile) = compiler.compile (source) } object ScalaTransformer { - def create(context: BundleContext) = { +// def file (url: URL) : AbstractFile = { +// if ("file" == url.getProtocol) { +// new PlainFile (new File (url.toURI)) +// } else { +// AbstractFile.getURL(url) +// } +// } + + def create (context: BundleContext) : ScalaTransformer = { val bundles : List[AbstractFile] = if (context == null) { List() } else { @@ -72,9 +72,16 @@ object ScalaTransformer { val jar = new File(context.getProperty("karaf.base"), context.getProperty("karaf.framework." + framework)) AbstractFile.getDirectory(jar) :: Bundles.create(context.getBundles) } - new ScalaTransformer(bundles) + create (bundles) } - def create(libraries: List[AbstractFile]) = new ScalaTransformer(libraries) + def create (libraries: List[AbstractFile]) : ScalaTransformer = + new ScalaTransformer(libraries) -} \ No newline at end of file + def transform (context: BundleContext, url: URL) = { + val source = ScalaSource (url) + //val manifest = manifest(sourceFile) + create(context).transform(source) + } + +} diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 5afab69..3c7ffc7 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -72,8 +72,7 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { source } - ScalaTransformer.create(bundleContext).transform(url) - + ScalaTransformer.transform (bundleContext, url) } catch { diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index ca18698..8f9cd2a 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -2,6 +2,9 @@ * Copyright (C) FuseSource, Inc. * http://fusesource.com * + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * * Licensed 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 @@ -16,17 +19,16 @@ */ package org.fusesource.slang.scala.deployer.archiver +import java.io._ +import java.net.URL +import java.util.Properties +import java.util.jar._ +import org.apache.commons.logging.LogFactory import tools.nsc.io.AbstractFile import tools.nsc.interpreter.AbstractFileClassLoader import org.osgi.framework.BundleActivator -import java.util.jar.JarFile.MANIFEST_NAME -import java.util.jar.{Attributes, Manifest, JarEntry, JarOutputStream} -import java.io.{ByteArrayOutputStream, ByteArrayInputStream, InputStream, OutputStream} import org.ops4j.pax.swissbox.bnd.BndUtils.createBundle - -import java.util.Properties -import org.apache.commons.logging.LogFactory -import java.net.URL +import org.fusesource.slang.scala.deployer.ScalaSource /** * Helper class that stores the contents of a Scala compile {@link AbstractFile} @@ -38,7 +40,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { val classloaders = bundles.map(new AbstractFileClassLoader(_, getClass.getClassLoader)) - def archive(dir: AbstractFile, url: URL) : InputStream = { + def archive(dir: AbstractFile, source: ScalaSource) : InputStream = { val classloader = createClassLoader(dir) val props = new Properties @@ -63,7 +65,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { bytes.close createBundle(new ByteArrayInputStream(bytes.toByteArray), - props, bsn(url)) + props, bsn(source.url)) } def entries(dir: AbstractFile)(action: (String, AbstractFile) => Unit) : Unit = diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index aa37a49..dfb8eaa 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -19,10 +19,10 @@ */ package org.fusesource.slang.scala.deployer.compiler -import tools.nsc.reporters.{AbstractReporter, Reporter} +import tools.nsc.reporters.AbstractReporter import org.apache.commons.logging.LogFactory -import tools.nsc.io.{VirtualDirectory, PlainFile, AbstractFile} -import tools.nsc.{Interpreter, Global, Settings} +import tools.nsc.io.{VirtualDirectory, AbstractFile} +import tools.nsc.{Global, Settings} import tools.nsc.util._ /** @@ -33,8 +33,8 @@ class ScalaCompiler(bundles: List[AbstractFile]) { final val LOG = LogFactory.getLog(classOf[ScalaCompiler]) - def compile(sources: List[AbstractFile]) : AbstractFile = { - LOG.info("Compiling " + sources) + def compile(source: AbstractFile) : AbstractFile = { + LOG.info("Compiling " + source) val dir = new VirtualDirectory("memory", None) settings.outputDirs.setSingleOutput(dir) @@ -62,7 +62,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { e.printStackTrace() throw e } - run.compileFiles(sources) + run.compileFiles (List(source)) dir @@ -71,6 +71,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val settings = new Settings lazy val reporter = new AbstractReporter { + def displayPrompt = println("compiler:") def display(position: Position, msg: String, severity: Severity): Unit = { @@ -80,7 +81,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { val settings = ScalaCompiler.this.settings } - lazy val compiler = new Global(settings, reporter) { + lazy val compiler = new Global(settings, reporter) { override def classPath = { require(!forMSIL, "MSIL not supported") @@ -94,7 +95,10 @@ class ScalaCompiler(bundles: List[AbstractFile]) { and injecting our OSGi bundles into this internal classpath. */ override def rootLoader = { val cp = classPath.asInstanceOf[ClassPath[AbstractFile]] - (new loaders.JavaPackageLoader (cp)).asInstanceOf[LazyType] + new loaders.JavaPackageLoader (cp) match { + case loader : LazyType => loader + case _ => throw new Exception ("Failed to create rootLoader of embedded Scala compiler.") + } } def createClassPath [T] (original: ClassPath[T]) = { diff --git a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala index 3ecf0fc..bd1a563 100644 --- a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala +++ b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala @@ -2,6 +2,9 @@ * Copyright (C) FuseSource, Inc. * http://fusesource.com * + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * * Licensed 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 @@ -44,7 +47,7 @@ class ScalaTransformerTest { @Test def testCompile = { - val source = this.getClass.getClassLoader.getResource("SimpleTest.scala") + val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala")) val result = transformer.compile(source) assertNotNull(result.lookupName("SimpleTest.class", false)) @@ -53,7 +56,7 @@ class ScalaTransformerTest { @Test def testTransform = { - val source = this.getClass.getClassLoader.getResource("SimpleTest.scala") + val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala")) val result = new ByteArrayOutputStream transformer.transform(source, result) @@ -66,7 +69,7 @@ class ScalaTransformerTest { @Test def testTransformWithActivator = { - val source = this.getClass.getClassLoader.getResource("TestWithActivator.scala") + val source = ScalaSource(this.getClass.getClassLoader.getResource("TestWithActivator.scala")) val result = new ByteArrayOutputStream() transformer.transform(source, result) From 11580776f3d39de58f0468f50c157f791d27eefa Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 16 Mar 2012 11:56:10 +0100 Subject: [PATCH 02/29] Including OSGi BundleContext in ScalaSource. Need to refactor tests. --- .../slang/scala/deployer/ScalaSource.scala | 29 +++++++++++++++---- .../scala/deployer/ScalaTransformer.scala | 28 +++++++----------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index f84c13b..387b19d 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -18,25 +18,44 @@ package org.fusesource.slang.scala.deployer import java.io.File import java.net.URL +import org.osgi.framework.BundleContext import tools.nsc.io.AbstractFile import tools.nsc.io.PlainFile +import compiler.Bundles trait ScalaSource extends AbstractFile { val url : URL + val context : BundleContext + override def toString = url.toString + val bundles = Option (context) match { + case None => + throw new Exception ("No BundleContext available to search for OSGi bundles.") + //List() + case Some (ctxt) => + val framework = ctxt.getProperty("karaf.framework") + val jar = new File( + ctxt.getProperty("karaf.base"), + ctxt.getProperty("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create(ctxt.getBundles) + } + } object ScalaSource { - def apply (u : URL) = u.getProtocol match { - case "file" => - new PlainFile (new File (u.toURI)) with ScalaSource { val url = u } + def apply (url : URL, ctxt : BundleContext) = (Option(url), Option(ctxt)) match { + case (Some(u), Some(c)) if u.getProtocol == "file" => + new PlainFile (new File (url.toURI)) with ScalaSource { + val url = u + val context = c + } case _ => - throw new Exception ("Protocol of a ScalaSource must be a file.") - //AbstractFile.getURL (url) with ScalaSource + throw new Exception ("Invalid URL or BundleContext for ScalaSource construction.") + // TODO: We should perhaps use AbstractFile.getURL(u) here. } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala index 70c6a90..a1363e2 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala @@ -24,7 +24,7 @@ import compiler.{Bundles, ScalaCompiler} import org.apache.commons.logging.LogFactory import tools.nsc.io.AbstractFile import java.net.URL -import org.osgi.framework.{BundleContext, Bundle} +import org.osgi.framework.BundleContext import java.io.{File, InputStream, OutputStream} class ScalaTransformer(val bundles: List[AbstractFile]) { @@ -56,32 +56,24 @@ class ScalaTransformer(val bundles: List[AbstractFile]) { object ScalaTransformer { -// def file (url: URL) : AbstractFile = { -// if ("file" == url.getProtocol) { -// new PlainFile (new File (url.toURI)) +// def create (context: BundleContext) : ScalaTransformer = { +// val bundles : List[AbstractFile] = if (context == null) { +// List() // } else { -// AbstractFile.getURL(url) +// val framework = context.getProperty("karaf.framework") +// val jar = new File(context.getProperty("karaf.base"), context.getProperty("karaf.framework." + framework)) +// AbstractFile.getDirectory(jar) :: Bundles.create(context.getBundles) // } +// create (bundles) // } - def create (context: BundleContext) : ScalaTransformer = { - val bundles : List[AbstractFile] = if (context == null) { - List() - } else { - val framework = context.getProperty("karaf.framework") - val jar = new File(context.getProperty("karaf.base"), context.getProperty("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create(context.getBundles) - } - create (bundles) - } - def create (libraries: List[AbstractFile]) : ScalaTransformer = new ScalaTransformer(libraries) def transform (context: BundleContext, url: URL) = { - val source = ScalaSource (url) + val source = ScalaSource (url, context) //val manifest = manifest(sourceFile) - create(context).transform(source) + create(source.bundles).transform(source) } } From 7833e0225f0effe1ba71da6ed47d1dd530271d59 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 16 Mar 2012 16:15:13 +0100 Subject: [PATCH 03/29] Putting compile() and archive() methods in ScalaSource. --- .../slang/scala/deployer/ScalaSource.scala | 30 +++++------ .../scala/deployer/ScalaTransformer.scala | 53 ++++++++++++++----- .../scala/deployer/ScalaTransformerTest.scala | 39 ++++++++------ 3 files changed, 74 insertions(+), 48 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 387b19d..dc01273 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -18,40 +18,36 @@ package org.fusesource.slang.scala.deployer import java.io.File import java.net.URL -import org.osgi.framework.BundleContext import tools.nsc.io.AbstractFile import tools.nsc.io.PlainFile -import compiler.Bundles +import compiler.ScalaCompiler +import archiver.ScalaArchiver trait ScalaSource extends AbstractFile { val url : URL - val context : BundleContext + val libs : List[AbstractFile] override def toString = url.toString - val bundles = Option (context) match { - case None => - throw new Exception ("No BundleContext available to search for OSGi bundles.") - //List() - case Some (ctxt) => - val framework = ctxt.getProperty("karaf.framework") - val jar = new File( - ctxt.getProperty("karaf.base"), - ctxt.getProperty("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create(ctxt.getBundles) - } + def compile () : AbstractFile = + (new ScalaCompiler (libs)).compile (this) + + def archive (dir : AbstractFile) = + (new ScalaArchiver (libs)).archive (dir, this) + + def transform () = archive(compile()) } object ScalaSource { - def apply (url : URL, ctxt : BundleContext) = (Option(url), Option(ctxt)) match { - case (Some(u), Some(c)) if u.getProtocol == "file" => + def apply (url : URL, libs : List[AbstractFile]) = (Option(url), Option(libs)) match { + case (Some(u), Some(l)) if u.getProtocol == "file" => new PlainFile (new File (url.toURI)) with ScalaSource { val url = u - val context = c + val libs = l } case _ => throw new Exception ("Invalid URL or BundleContext for ScalaSource construction.") diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala index a1363e2..d24d480 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala @@ -35,16 +35,16 @@ class ScalaTransformer(val bundles: List[AbstractFile]) { val archiver = new ScalaArchiver (bundles) - def transform(source: ScalaSource, stream: OutputStream) { - val result = transform(source) - val bytes = new Array[Byte](1024) - var read = result.read(bytes) - while (read > 0) { - stream.write(bytes, 0, read) - read = result.read(bytes) - } - result.close - } +// def transform(source: ScalaSource, stream: OutputStream) { +// val result = transform(source) +// val bytes = new Array[Byte](1024) +// var read = result.read(bytes) +// while (read > 0) { +// stream.write(bytes, 0, read) +// read = result.read(bytes) +// } +// result.close +// } def transform (source: ScalaSource) : InputStream = { LOG.info("Transforming " + source + " into an OSGi bundle") @@ -70,10 +70,35 @@ object ScalaTransformer { def create (libraries: List[AbstractFile]) : ScalaTransformer = new ScalaTransformer(libraries) - def transform (context: BundleContext, url: URL) = { - val source = ScalaSource (url, context) - //val manifest = manifest(sourceFile) - create(source.bundles).transform(source) + def transform (context: BundleContext, url: URL) : InputStream = { + val bundles = Option(context) match { + case None => + throw new Exception ("No BundleContext available to search for OSGi bundles.") + // TODO: Why not List()? + case Some (ctxt) => + val framework = ctxt.getProperty ("karaf.framework") + val jar = new File ( + ctxt.getProperty ("karaf.base"), + ctxt.getProperty ("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) + } + transform (bundles, url) } + def transform (libraries: List[AbstractFile], url: URL) = { + val source = ScalaSource (url, libraries) + // val manifest = manifest (source) + create(source.libs).transform(source) + } + + def transform (libraries: List[AbstractFile], url: URL, stream: OutputStream) { + val result = transform (libraries, url) + val bytes = new Array[Byte] (1024) + var read = result.read(bytes) + while (read > 0) { + stream.write(bytes, 0, read) + read = result.read (bytes) + } + result.close + } } diff --git a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala index bd1a563..60b0b5c 100644 --- a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala +++ b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala @@ -31,7 +31,8 @@ import org.osgi.framework.BundleContext */ class ScalaTransformerTest { - var transformer : ScalaTransformer = null + //var transformer : ScalaTransformer = null + var libraries : List[AbstractFile] = Nil lazy val repository = if (System.getProperty("maven.local.repo") != null) { new File(System.getProperty("maven.local.repo")) @@ -41,14 +42,14 @@ class ScalaTransformerTest { @Before def createTransformer = { - val library = new File(repository, "org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar") - transformer = ScalaTransformer.create(List(AbstractFile.getFile(library))) + val scalaLib = new File(repository, "org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar") + libraries = List(AbstractFile.getFile(scalaLib)) } @Test def testCompile = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala")) - val result = transformer.compile(source) + val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) + val result = source.compile() assertNotNull(result.lookupName("SimpleTest.class", false)) assertNotNull(result.lookupPath("org/test/AnotherSimpleTest.class", false)) @@ -56,12 +57,14 @@ class ScalaTransformerTest { @Test def testTransform = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala")) - val result = new ByteArrayOutputStream - - transformer.transform(source, result) - - var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) + val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) + val result = source.transform () + //val result = new ByteArrayOutputStream + // + //ScalaTransformer.transform (libraries, source, result) + // + //var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) + var jar = new JarInputStream(result) var entries = getEntries(jar) assertTrue(entries.contains("SimpleTest.class")) assertTrue(entries.contains("org/test/AnotherSimpleTest.class")) @@ -69,12 +72,14 @@ class ScalaTransformerTest { @Test def testTransformWithActivator = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("TestWithActivator.scala")) - val result = new ByteArrayOutputStream() - - transformer.transform(source, result) - - var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) + val source = ScalaSource(this.getClass.getClassLoader.getResource("TestWithActivator.scala"), libraries) + val result = source.transform () + //val result = new ByteArrayOutputStream() + // + //transformer.transform(source, result) + // + //var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) + var jar = new JarInputStream(result) var entries = getEntries(jar) assertTrue(entries.contains("org/test/TestWithActivator.class")) From dcd558d2f17464efb7d38c659915a71314e01f52 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 16 Mar 2012 17:16:16 +0100 Subject: [PATCH 04/29] Removing ScalaTransformer. --- .../slang/scala/deployer/ScalaSource.scala | 33 +++++- .../scala/deployer/ScalaTransformer.scala | 104 ------------------ .../scala/deployer/ScalaURLHandler.scala | 5 +- 3 files changed, 34 insertions(+), 108 deletions(-) delete mode 100644 scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index dc01273..779affb 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -18,26 +18,38 @@ package org.fusesource.slang.scala.deployer import java.io.File import java.net.URL +import org.apache.commons.logging.LogFactory +import org.osgi.framework.BundleContext import tools.nsc.io.AbstractFile import tools.nsc.io.PlainFile +import compiler.Bundles import compiler.ScalaCompiler import archiver.ScalaArchiver trait ScalaSource extends AbstractFile { + final val LOG = LogFactory.getLog(classOf[ScalaSource]) + val url : URL val libs : List[AbstractFile] override def toString = url.toString - def compile () : AbstractFile = + def compile () : AbstractFile = { + LOG.debug ("Compiling " + this + " using embedded Scala compiler.") (new ScalaCompiler (libs)).compile (this) + } - def archive (dir : AbstractFile) = + def archive (dir : AbstractFile) = { + LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") (new ScalaArchiver (libs)).archive (dir, this) + } - def transform () = archive(compile()) + def transform () = { + LOG.info ("Transforming " + this + " into an OSGi bundle.") + archive (compile ()) + } } @@ -54,4 +66,19 @@ object ScalaSource { // TODO: We should perhaps use AbstractFile.getURL(u) here. } + def apply (url : URL, context : BundleContext) : ScalaSource = { + val bundles = Option(context) match { + case None => + throw new Exception ("No BundleContext available to search for OSGi bundles.") + // TODO: Why not List()? + case Some (ctxt) => + val framework = ctxt.getProperty ("karaf.framework") + val jar = new File ( + ctxt.getProperty ("karaf.base"), + ctxt.getProperty ("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) + } + ScalaSource (url, bundles) + } + } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala deleted file mode 100644 index d24d480..0000000 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaTransformer.scala +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (C) FuseSource, Inc. - * http://fusesource.com - * - * Copyright (C) Crossing-Tech SA, 2012. - * Contact: - * - * Licensed 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. - */ -package org.fusesource.slang.scala.deployer - -import archiver.ScalaArchiver -import compiler.{Bundles, ScalaCompiler} -import org.apache.commons.logging.LogFactory -import tools.nsc.io.AbstractFile -import java.net.URL -import org.osgi.framework.BundleContext -import java.io.{File, InputStream, OutputStream} - -class ScalaTransformer(val bundles: List[AbstractFile]) { - - final val LOG = LogFactory.getLog(classOf[ScalaTransformer]) - - val compiler = new ScalaCompiler (bundles) - - val archiver = new ScalaArchiver (bundles) - -// def transform(source: ScalaSource, stream: OutputStream) { -// val result = transform(source) -// val bytes = new Array[Byte](1024) -// var read = result.read(bytes) -// while (read > 0) { -// stream.write(bytes, 0, read) -// read = result.read(bytes) -// } -// result.close -// } - - def transform (source: ScalaSource) : InputStream = { - LOG.info("Transforming " + source + " into an OSGi bundle") - archiver.archive(compile(source), source) - } - - def compile (source: AbstractFile) = compiler.compile (source) -} - -object ScalaTransformer { - -// def create (context: BundleContext) : ScalaTransformer = { -// val bundles : List[AbstractFile] = if (context == null) { -// List() -// } else { -// val framework = context.getProperty("karaf.framework") -// val jar = new File(context.getProperty("karaf.base"), context.getProperty("karaf.framework." + framework)) -// AbstractFile.getDirectory(jar) :: Bundles.create(context.getBundles) -// } -// create (bundles) -// } - - def create (libraries: List[AbstractFile]) : ScalaTransformer = - new ScalaTransformer(libraries) - - def transform (context: BundleContext, url: URL) : InputStream = { - val bundles = Option(context) match { - case None => - throw new Exception ("No BundleContext available to search for OSGi bundles.") - // TODO: Why not List()? - case Some (ctxt) => - val framework = ctxt.getProperty ("karaf.framework") - val jar = new File ( - ctxt.getProperty ("karaf.base"), - ctxt.getProperty ("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) - } - transform (bundles, url) - } - - def transform (libraries: List[AbstractFile], url: URL) = { - val source = ScalaSource (url, libraries) - // val manifest = manifest (source) - create(source.libs).transform(source) - } - - def transform (libraries: List[AbstractFile], url: URL, stream: OutputStream) { - val result = transform (libraries, url) - val bytes = new Array[Byte] (1024) - var read = result.read(bytes) - while (read > 0) { - stream.write(bytes, 0, read) - read = result.read (bytes) - } - result.close - } -} diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 3c7ffc7..1f16e3f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -72,7 +72,10 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { source } - ScalaTransformer.transform (bundleContext, url) + val script = ScalaSource (url, bundleContext) + script.transform() + + //ScalaTransformer.transform (bundleContext, url) } catch { From 0b867d0afdd300ffe7763627f249f0dff8da4ef1 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 16 Mar 2012 18:47:04 +0100 Subject: [PATCH 05/29] Cleaning up implementation of bundles. --- .../scala/deployer/ScalaURLHandler.scala | 22 ++--- .../scala/deployer/compiler/Bundles.scala | 84 +++++++------------ 2 files changed, 34 insertions(+), 72 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 1f16e3f..7aa9094 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -19,21 +19,12 @@ */ package org.fusesource.slang.scala.deployer -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.io.IOException -import java.io.InputStream -import java.net.MalformedURLException -import java.net.URL -import java.net.URLConnection -import org.apache.commons.logging.Log -import org.apache.commons.logging.LogFactory -import org.osgi.service.url.AbstractURLStreamHandlerService import reflect.BeanProperty +import java.io._ +import java.net._ +import org.apache.commons.logging._ +import org.osgi.service.url.AbstractURLStreamHandlerService import org.osgi.framework.BundleContext -import org.ops4j.pax.swissbox.bnd.BndUtils.createBundle -import java.util.Properties -import org.ops4j.pax.swissbox.bnd.OverwriteMode.MERGE /** * A URL handler that will transform a Scala source file into an OSGi bundle @@ -72,10 +63,7 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { source } - val script = ScalaSource (url, bundleContext) - script.transform() - - //ScalaTransformer.transform (bundleContext, url) + ScalaSource(url, bundleContext).transform() } catch { diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index 8cb0946..6dc838f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -19,12 +19,12 @@ */ package org.fusesource.slang.scala.deployer.compiler -import org.osgi.framework.Bundle -import java.io.{InputStream, IOException, File} -import scala.tools.nsc.io.{PlainFile, AbstractFile} -import java.net.{URISyntaxException, URL} +import annotation.tailrec +import java.io._ +import java.net._ import org.apache.commons.logging.LogFactory -import java.lang.String +import org.osgi.framework.Bundle +import tools.nsc.io.{AbstractFile, PlainFile} /** * Helper methods to transform OSGi bundles into {@link AbstractFile} implementations @@ -93,62 +93,36 @@ object Bundles { */ def isDirectory: Boolean = true - override def elements: Iterator[AbstractFile] = { - new Iterator[AbstractFile]() { - val dirs = bundle.getEntryPaths(fullName) - var nextEntry = prefetch() - - def hasNext() = { - if (nextEntry == null) - nextEntry = prefetch() - - nextEntry != null - } - - def next() = { - if (hasNext()) { - val entry = nextEntry - nextEntry = null - entry - } - else { - throw new NoSuchElementException() - } - } - - private def prefetch() = { - if (dirs.hasMoreElements) { - val entry = dirs.nextElement.asInstanceOf[String] - var entryUrl = bundle.getResource("/" + entry) - - // Bundle.getResource seems to be inconsistent with respect to requiring - // a trailing slash - if (entryUrl == null) - entryUrl = bundle.getResource("/" + removeTralingSlash(entry)) + override def elements : Iterator[AbstractFile] = { - // If still null OSGi wont let use load that resource for some reason - if (entryUrl == null) { - null - } - else { - if (entry.endsWith(".class")) - new FileEntry(bundle, entryUrl, DirEntry.this) - else - new DirEntry(bundle, entryUrl, DirEntry.this) - } - } - else - null - } - - private def removeTralingSlash(s: String): String = + @tailrec + def removeTrailingSlash(s: String): String = if (s == null || s.length == 0) s else if (s.last == '/') - removeTralingSlash(s.substring(0, s.length - 1)) + removeTrailingSlash(s.substring(0, s.length - 1)) else s - } + + import scala.collection.JavaConverters._ + bundle.getEntryPaths(fullName).asScala.map { + case entry : String => { + val entryUrl = Option(Option(bundle.getResource("/" + entry)). + // Bundle.getReource seems to be inconsistent with respect to requiring + // a trailing slash. + getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) + entryUrl match { + case None => + throw new IllegalStateException ("For some reason, OSGi will not let use the entry " + entry) + case Some(url) => + if (entry.endsWith(".class")) + new FileEntry(bundle, url, DirEntry.this) + else new DirEntry(bundle, url, DirEntry.this) + } + } + case _ => + throw new ClassCastException("Items other than Strings found in an OSGi bundle's entry paths.") + } } def lookupName(name: String, directory: Boolean): AbstractFile = { From 62f446beedb78fa2b502ea13aae678ba222ff8e9 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Mon, 19 Mar 2012 14:49:23 +0100 Subject: [PATCH 06/29] AbstractFile interface is of no use to rewrite Scala code. --- .../slang/scala/deployer/ScalaSource.scala | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 779affb..cd18cb9 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -16,7 +16,7 @@ */ package org.fusesource.slang.scala.deployer -import java.io.File +import java.io._ import java.net.URL import org.apache.commons.logging.LogFactory import org.osgi.framework.BundleContext @@ -30,11 +30,11 @@ trait ScalaSource extends AbstractFile { final val LOG = LogFactory.getLog(classOf[ScalaSource]) - val url : URL + def url : URL - val libs : List[AbstractFile] + def libs : List[AbstractFile] - override def toString = url.toString + override def toString () = url.toString def compile () : AbstractFile = { LOG.debug ("Compiling " + this + " using embedded Scala compiler.") @@ -51,6 +51,30 @@ trait ScalaSource extends AbstractFile { archive (compile ()) } + /* It should be noted that the Scala compiler has the following piece of + code to read so-called AbstractFiles. See SourceReader.scala, lines + 48 to 59 in the compiler source code. + + def read(file: AbstractFile): Array[Char] = { + try file match { + case p: PlainFile => read(p.file) + case z: ZipArchive#Entry => read(Channels.newChannel(z.input)) + case _ => read(ByteBuffer.wrap(file.toByteArray)) + } + catch { + case e: Exception => reportEncodingError("" + file) ; Array() + } + } + + The big problem about this pattern-matching is that the principle of + a common interface using the "toByteArray" method is invalidated. In + our specific case, this means that it useless to override the input(), + toCharArray() or toByteArray() methods to intercept and rewrite on the + fly what is read from the file. */ + + def manifest () { + /* TODO: Extract manifest from this abstract file. */ + } } object ScalaSource { From 0ef2527dc417ec6b39ab5cac0858c3732a35e52d Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Mon, 19 Mar 2012 15:10:20 +0100 Subject: [PATCH 07/29] Cleaning up. --- .../scala/deployer/compiler/Bundles.scala | 37 ++++--------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index 6dc838f..05198d4 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -55,10 +55,8 @@ object Bundles { catch { case _ => 0 } @throws(classOf[IOException]) - def container: AbstractFile = - valueOrElse(parent) { - throw new IOException("No container") - } + def container: AbstractFile = Option(parent).getOrElse( + throw new IOException ("No container")) @throws(classOf[IOException]) def input: InputStream = url.openStream() @@ -127,11 +125,12 @@ object Bundles { def lookupName(name: String, directory: Boolean): AbstractFile = { val entry = bundle.getEntry(fullName + "/" + name) - nullOrElse(entry) { entry => - if (directory) - new DirEntry(bundle, entry, DirEntry.this) - else - new FileEntry(bundle, entry, DirEntry.this) + Option(entry) match { + case None => null + case Some (_) if directory => + new DirEntry (bundle, entry, DirEntry.this) + case Some (_) => + new FileEntry (bundle, entry, DirEntry.this) } } @@ -206,27 +205,7 @@ object Bundles { */ def create(bundle: Bundle): AbstractFile = { require(bundle != null, "bundle must not be null") - new DirEntry(bundle, bundle.getResource("/"), null) } - - /** - * Evaluate f on s if s is not null. - * @param s - * @param f - * @return f(s) if s is not null, null otherwise. - */ - def nullOrElse[S, T](s: S)(f: S => T): T = - if (s == null) null.asInstanceOf[T] - else f(s) - - /** - * @param t - * @param default - * @return t or default if null. - */ - def valueOrElse[T](t: T)(default: => T) = - if (t == null) default - else t } From 827e6a21862bbb210a77f391a8366607f46bb3a2 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Mon, 19 Mar 2012 16:17:56 +0100 Subject: [PATCH 08/29] Stubbed out PlainFile in favor of AbstractFile. Unit tests fail. --- .../slang/scala/deployer/ScalaSource.scala | 116 +++++++++++------- .../scala/deployer/ScalaURLHandler.scala | 2 +- .../scala/deployer/ScalaTransformerTest.scala | 54 ++++---- 3 files changed, 92 insertions(+), 80 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index cd18cb9..7de964f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -26,30 +26,29 @@ import compiler.Bundles import compiler.ScalaCompiler import archiver.ScalaArchiver -trait ScalaSource extends AbstractFile { +class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends AbstractFile { final val LOG = LogFactory.getLog(classOf[ScalaSource]) - def url : URL + if ((libraries == null) || libraries.exists(_ == null)) + throw new Exception ("Invalid libraries for ScalaSource constructor.") - def libs : List[AbstractFile] + if (url == null) + throw new Exception ("Invalid URL for ScalaSource constructor.") - override def toString () = url.toString - - def compile () : AbstractFile = { - LOG.debug ("Compiling " + this + " using embedded Scala compiler.") - (new ScalaCompiler (libs)).compile (this) - } - - def archive (dir : AbstractFile) = { - LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") - (new ScalaArchiver (libs)).archive (dir, this) - } - - def transform () = { - LOG.info ("Transforming " + this + " into an OSGi bundle.") - archive (compile ()) - } + def this (url : URL, context : BundleContext) = this (url, + Option(context) match { + case None => + throw new Exception ("No BundleContext available to search for OSGi bundles.") + // TODO: Why not List()? + case Some (ctxt) => + val framework = ctxt.getProperty ("karaf.framework") + val jar = new File ( + ctxt.getProperty ("karaf.base"), + ctxt.getProperty ("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) + } + ) /* It should be noted that the Scala compiler has the following piece of code to read so-called AbstractFiles. See SourceReader.scala, lines @@ -70,39 +69,62 @@ trait ScalaSource extends AbstractFile { a common interface using the "toByteArray" method is invalidated. In our specific case, this means that it useless to override the input(), toCharArray() or toByteArray() methods to intercept and rewrite on the - fly what is read from the file. */ + fly what is read from the file. - def manifest () { - /* TODO: Extract manifest from this abstract file. */ - } -} + We therefore chose not to inherit from the PlainFile, but to prefer + composition over inheritance. Which the reason why we have a plainFile + field: fooling this pattern-matching. */ -object ScalaSource { + val plainFile : PlainFile = new PlainFile (new File (url.toURI)) - def apply (url : URL, libs : List[AbstractFile]) = (Option(url), Option(libs)) match { - case (Some(u), Some(l)) if u.getProtocol == "file" => - new PlainFile (new File (url.toURI)) with ScalaSource { - val url = u - val libs = l - } - case _ => - throw new Exception ("Invalid URL or BundleContext for ScalaSource construction.") - // TODO: We should perhaps use AbstractFile.getURL(u) here. + override def name : String = plainFile.name + + override def path : String = plainFile.path + + override def absolute : AbstractFile = plainFile.absolute + + override def container : AbstractFile = plainFile.container + + override def file : File = plainFile.file + + override def create () : Unit = plainFile.create () + + override def delete () : Unit = plainFile.delete () + + override def isDirectory : Boolean = plainFile.isDirectory + + override def lastModified : Long = plainFile.lastModified + + override def input : InputStream = plainFile.input + + override def output : OutputStream = plainFile.output + + override def iterator : Iterator[AbstractFile] = plainFile.iterator + + override def lookupName (name : String, directory : Boolean) : AbstractFile = + plainFile.lookupName (name, directory) + + override def lookupNameUnchecked (name : String, directory : Boolean) : AbstractFile = + plainFile.lookupNameUnchecked (name, directory) + + override def toString () = url.toString + + def compile () : AbstractFile = { + LOG.debug ("Compiling " + this + " using embedded Scala compiler.") + (new ScalaCompiler (libraries)).compile (this) } - def apply (url : URL, context : BundleContext) : ScalaSource = { - val bundles = Option(context) match { - case None => - throw new Exception ("No BundleContext available to search for OSGi bundles.") - // TODO: Why not List()? - case Some (ctxt) => - val framework = ctxt.getProperty ("karaf.framework") - val jar = new File ( - ctxt.getProperty ("karaf.base"), - ctxt.getProperty ("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) - } - ScalaSource (url, bundles) + def archive (dir : AbstractFile) = { + LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") + (new ScalaArchiver (libraries)).archive (dir, this) } + def transform () = { + LOG.info ("Transforming " + this + " into an OSGi bundle.") + archive (compile ()) + } + + def manifest () { + /* TODO: Extract manifest from this abstract file. */ + } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 7aa9094..8e95df3 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -63,7 +63,7 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { source } - ScalaSource(url, bundleContext).transform() + new ScalaSource (url, bundleContext).transform() } catch { diff --git a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala index 60b0b5c..8494dbe 100644 --- a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala +++ b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala @@ -34,60 +34,50 @@ class ScalaTransformerTest { //var transformer : ScalaTransformer = null var libraries : List[AbstractFile] = Nil lazy val repository = - if (System.getProperty("maven.local.repo") != null) { - new File(System.getProperty("maven.local.repo")) + if (System.getProperty ("maven.local.repo") != null) { + new File (System.getProperty ("maven.local.repo")) } else { - new File(new File(System.getProperty("user.home"), ".m2"), "repository") + new File (new File (System.getProperty ("user.home"), ".m2"), "repository") } @Before def createTransformer = { - val scalaLib = new File(repository, "org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar") - libraries = List(AbstractFile.getFile(scalaLib)) + val scalaLib = new File (repository, "org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar") + libraries = List (AbstractFile.getFile(scalaLib)) } @Test def testCompile = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) - val result = source.compile() + val source = new ScalaSource (this.getClass.getClassLoader.getResource ("SimpleTest.scala"), libraries) + val result = source.compile () - assertNotNull(result.lookupName("SimpleTest.class", false)) - assertNotNull(result.lookupPath("org/test/AnotherSimpleTest.class", false)) + assertNotNull (result.lookupName ("SimpleTest.class", false)) + assertNotNull (result.lookupPath ("org/test/AnotherSimpleTest.class", false)) } @Test def testTransform = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) + val source = new ScalaSource (this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) val result = source.transform () - //val result = new ByteArrayOutputStream - // - //ScalaTransformer.transform (libraries, source, result) - // - //var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) - var jar = new JarInputStream(result) - var entries = getEntries(jar) - assertTrue(entries.contains("SimpleTest.class")) - assertTrue(entries.contains("org/test/AnotherSimpleTest.class")) + var jar = new JarInputStream (result) + var entries = getEntries (jar) + assertTrue (entries.contains ("SimpleTest.class")) + assertTrue (entries.contains ("org/test/AnotherSimpleTest.class")) } @Test def testTransformWithActivator = { - val source = ScalaSource(this.getClass.getClassLoader.getResource("TestWithActivator.scala"), libraries) + val source = new ScalaSource (this.getClass.getClassLoader.getResource ("TestWithActivator.scala"), libraries) val result = source.transform () - //val result = new ByteArrayOutputStream() - // - //transformer.transform(source, result) - // - //var jar = new JarInputStream(new ByteArrayInputStream(result.toByteArray)) - var jar = new JarInputStream(result) - var entries = getEntries(jar) - assertTrue(entries.contains("org/test/TestWithActivator.class")) + var jar = new JarInputStream (result) + var entries = getEntries (jar) + assertTrue (entries.contains ("org/test/TestWithActivator.class")) val manifest = jar.getManifest; - assertEquals("BundleActivator class should have been automatically detected", - "org.test.TestWithActivator", manifest.getMainAttributes.getValue("Bundle-Activator")) - assertTrue("Bundle-SymbolicName should have a decent value", - manifest.getMainAttributes().getValue("Bundle-SymbolicName").endsWith("TestWithActivator")); + assertEquals ("BundleActivator class should have been automatically detected", + "org.test.TestWithActivator", manifest.getMainAttributes.getValue ("Bundle-Activator")) + assertTrue ("Bundle-SymbolicName should have a decent value", + manifest.getMainAttributes().getValue("Bundle-SymbolicName").endsWith("TestWithActivator")); } From 62b28b67bfcd2bc96e40cae5822891014f7a270c Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Mon, 19 Mar 2012 19:53:12 +0100 Subject: [PATCH 09/29] SizeOption is overriden. Unit tests are OK. --- .../slang/scala/deployer/ScalaSource.scala | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 7de964f..3d311ba 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -97,8 +97,20 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab override def input : InputStream = plainFile.input + override def toByteArray : Array[Byte] = + + /* NOTE: If the sizeOption is not properly overriden, the AbstractFile + default implementation of sizeOption will blow up. Hence the 'catch'. + + These composition vs. inheritance bugs are hard to find. In case this + happens, continue delegating calls to plainFile. */ + + try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} + override def output : OutputStream = plainFile.output + override def sizeOption = plainFile.sizeOption + override def iterator : Iterator[AbstractFile] = plainFile.iterator override def lookupName (name : String, directory : Boolean) : AbstractFile = @@ -107,7 +119,11 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab override def lookupNameUnchecked (name : String, directory : Boolean) : AbstractFile = plainFile.lookupNameUnchecked (name, directory) - override def toString () = url.toString + override def toString () = + /* This call needs to be delegated to ensure that the referenced file is + named properly. The implementation in PlainFile removes the file: URI + prefix that is fed to a ScalaSource instance at construct-time. */ + plainFile.toString def compile () : AbstractFile = { LOG.debug ("Compiling " + this + " using embedded Scala compiler.") From cf74249036d2490156ebd0384a30c482a9e1ae21 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Wed, 21 Mar 2012 10:20:52 +0100 Subject: [PATCH 10/29] Trying to hook in parsing of manifest in comments. --- .../deployer/ScalaDeploymentListener.scala | 11 +++--- .../slang/scala/deployer/ScalaSource.scala | 15 ++++++++ .../scala/deployer/parser/CommentParser.scala | 35 +++++++++++++++++++ .../src/test/resources/SimpleTest.scala | 9 ++++- 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala index ed8aabb..57e210c 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala @@ -2,6 +2,9 @@ * Copyright (C) FuseSource, Inc. * http://fusesource.com * + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * * Licensed 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 @@ -30,16 +33,16 @@ class ScalaDeploymentListener extends ArtifactUrlTransformer { val LOG = LogFactory.getLog(classOf[ScalaDeploymentListener]) def canHandle(artifact: File) = { - artifact.isFile() && artifact.getName().endsWith(".scala") + artifact.isFile && artifact.getName.endsWith(".scala") } def transform(artifact: URL) : URL = { try { - new URL("scala", null, artifact.toString()); + new URL("scala", null, artifact.toString) } catch { case e: Exception => { - LOG.error("Unable to build scala bundle", e); - return null; + LOG.error("Unable to build scala bundle", e) + null } } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 3d311ba..6250bc4 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -2,6 +2,9 @@ * Copyright (C) Crossing-Tech SA, 2012. * Contact: * + * Copyright (C) FuseSource, Inc. + * http://fusesource.com + * * Licensed 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 @@ -50,6 +53,8 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab } ) + /**********************************************************************/ + /* It should be noted that the Scala compiler has the following piece of code to read so-called AbstractFiles. See SourceReader.scala, lines 48 to 59 in the compiler source code. @@ -125,6 +130,8 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab prefix that is fed to a ScalaSource instance at construct-time. */ plainFile.toString + /**********************************************************************/ + def compile () : AbstractFile = { LOG.debug ("Compiling " + this + " using embedded Scala compiler.") (new ScalaCompiler (libraries)).compile (this) @@ -137,10 +144,18 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab def transform () = { LOG.info ("Transforming " + this + " into an OSGi bundle.") + manifest () archive (compile ()) } def manifest () { + import parser.CommentParser._ + + val source = io.Source.fromInputStream(input).getLines().mkString("\n") + //LOG.info ("Manifest: \n" + source) + + val c = parseComment(source) + LOG.info("Comment:\n" + c) /* TODO: Extract manifest from this abstract file. */ } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala new file mode 100644 index 0000000..e20a768 --- /dev/null +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala @@ -0,0 +1,35 @@ +/** + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * + * Licensed 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. + */ +package org.fusesource.slang.scala.deployer.parser + +import scala.util.parsing.combinator._ + +object CommentParser extends RegexParsers { + + override def skipWhitespace = false + + private def openComment = regex("""/\*""".r) + + private def closeComment = regex("""\*/""".r) + + private def textComment = regex("""^(((?!\*/).|\n))*""".r) + + private def comment = openComment ~> textComment <~ closeComment + + def parseComment (s : String) : ParseResult[Any] = parse (comment, s) + +} diff --git a/scala/deployer/src/test/resources/SimpleTest.scala b/scala/deployer/src/test/resources/SimpleTest.scala index 08696c1..b9de63b 100644 --- a/scala/deployer/src/test/resources/SimpleTest.scala +++ b/scala/deployer/src/test/resources/SimpleTest.scala @@ -2,6 +2,9 @@ * Copyright (C) FuseSource, Inc. * http://fusesource.com * + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * * Licensed 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 @@ -14,6 +17,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** OSGI-MANIFEST: + */ + class SimpleTest { def isWorking = true @@ -26,4 +33,4 @@ package org.test { -} \ No newline at end of file +} From e177e08ac883e9d185751ebde76337ef7ef9eeb9 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Wed, 21 Mar 2012 11:34:57 +0100 Subject: [PATCH 11/29] Better parsing of Scala scripts. --- .../slang/scala/deployer/ScalaSource.scala | 6 +++-- .../scala/deployer/parser/CommentParser.scala | 27 +++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 6250bc4..ce9468e 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -149,12 +149,14 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab } def manifest () { - import parser.CommentParser._ val source = io.Source.fromInputStream(input).getLines().mkString("\n") //LOG.info ("Manifest: \n" + source) - val c = parseComment(source) + import parser.CommentParser._ + import scala.util.parsing.combinator._ + + val c : ParseResult[List[parser.Item]] = parse(source) LOG.info("Comment:\n" + c) /* TODO: Extract manifest from this abstract file. */ } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala index e20a768..96b45ac 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala @@ -18,18 +18,35 @@ package org.fusesource.slang.scala.deployer.parser import scala.util.parsing.combinator._ +sealed abstract class Item +case class Code (code : String) extends Item +case class Comment (code : String) extends Item + object CommentParser extends RegexParsers { override def skipWhitespace = false - private def openComment = regex("""/\*""".r) + private def spaces = regex("""[ \t\n]*""".r) + + private def openComment = spaces ~> regex("""/\*""".r) + + private def closeComment = regex("""\*/""".r) <~ spaces + + private def textComment = regex("""^((?!\*/).|\n)*""".r) - private def closeComment = regex("""\*/""".r) + private def comment : Parser[Comment] = openComment ~> textComment <~ closeComment ^^ { case s : String => println("Found comment"); Comment(s) } - private def textComment = regex("""^(((?!\*/).|\n))*""".r) + /* NOTE: Use + instead of * in the following regexp + to avoid infinite loops while parsing. */ + private def code : Parser[Code] = regex("""^((?!/\*).|\n)+""".r) ^^ { case s : String => println("Found code"); Code(s) } - private def comment = openComment ~> textComment <~ closeComment + private def items : Parser[List[Item]] = (( comment | code ) * ) - def parseComment (s : String) : ParseResult[Any] = parse (comment, s) + def parse (s : String) : ParseResult[List[Item]] = { + println("Parsing") + val res = parse (items, s) + println("Parsed") + res + } } From 08702873637b23066ed2b59b7df62585a3e23d7c Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Wed, 21 Mar 2012 13:51:26 +0100 Subject: [PATCH 12/29] Able to extract manifest when parsing. --- .../slang/scala/deployer/ScalaSource.scala | 2 +- ...CommentParser.scala => ScriptParser.scala} | 35 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) rename scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/{CommentParser.scala => ScriptParser.scala} (58%) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index ce9468e..bb21598 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -153,7 +153,7 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab val source = io.Source.fromInputStream(input).getLines().mkString("\n") //LOG.info ("Manifest: \n" + source) - import parser.CommentParser._ + import parser.ScriptParser._ import scala.util.parsing.combinator._ val c : ParseResult[List[parser.Item]] = parse(source) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala similarity index 58% rename from scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala rename to scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala index 96b45ac..6241f11 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/CommentParser.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala @@ -20,9 +20,32 @@ import scala.util.parsing.combinator._ sealed abstract class Item case class Code (code : String) extends Item -case class Comment (code : String) extends Item -object CommentParser extends RegexParsers { +abstract class Commented extends Item +case class Comment (code : String) extends Commented +case class Manifest extends Commented + +object ManifestParser extends RegexParsers { + + override def skipWhitespace = false + + private def spaces = regex("""([ \t\n]|\n[ \t]*\*[ \t]*)*""".r) + + private def manifestHeader = spaces ~> regex("""OSGI-MANIFEST:""".r) <~ spaces ^^ { case _ : String => {}} + + private def manifest = regex("""\**""".r) ~> manifestHeader + + def parse (comment : Comment) : Boolean = comment match { + case Comment (c) => parse (manifest, c) match { + case Success ((), _) => true + case Failure (msg, _) => println (msg); false + case Error (msg, _) => throw new Exception ( + "Slang deployer parsing error: " + msg) + }} + +} + +object ScriptParser extends RegexParsers { override def skipWhitespace = false @@ -32,9 +55,13 @@ object CommentParser extends RegexParsers { private def closeComment = regex("""\*/""".r) <~ spaces - private def textComment = regex("""^((?!\*/).|\n)*""".r) + private def textComment = regex("""^((?!\*/).|\n)*""".r) ^^ (Comment(_)) - private def comment : Parser[Comment] = openComment ~> textComment <~ closeComment ^^ { case s : String => println("Found comment"); Comment(s) } + private def comment : Parser[Commented] = openComment ~> textComment <~ closeComment ^^ { + case c : Comment => ManifestParser.parse(c) match { + case true => Manifest () + case false => c + }} /* NOTE: Use + instead of * in the following regexp to avoid infinite loops while parsing. */ From 0b5528312ce7e16c04523420d57628a56e3e829a Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Wed, 21 Mar 2012 13:54:40 +0100 Subject: [PATCH 13/29] Cleaning up printlns. --- .../slang/scala/deployer/parser/ScriptParser.scala | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala index 6241f11..b4cb797 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala @@ -38,7 +38,7 @@ object ManifestParser extends RegexParsers { def parse (comment : Comment) : Boolean = comment match { case Comment (c) => parse (manifest, c) match { case Success ((), _) => true - case Failure (msg, _) => println (msg); false + case Failure (msg, _) => false case Error (msg, _) => throw new Exception ( "Slang deployer parsing error: " + msg) }} @@ -65,15 +65,10 @@ object ScriptParser extends RegexParsers { /* NOTE: Use + instead of * in the following regexp to avoid infinite loops while parsing. */ - private def code : Parser[Code] = regex("""^((?!/\*).|\n)+""".r) ^^ { case s : String => println("Found code"); Code(s) } + private def code : Parser[Code] = regex("""^((?!/\*).|\n)+""".r) ^^ (Code(_)) private def items : Parser[List[Item]] = (( comment | code ) * ) - def parse (s : String) : ParseResult[List[Item]] = { - println("Parsing") - val res = parse (items, s) - println("Parsed") - res - } + def parse (s : String) : ParseResult[List[Item]] = parse (items, s) } From 68c62a32c492f2ad071f85ff7fd62bee2be2019a Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 23 Mar 2012 17:21:57 +0100 Subject: [PATCH 14/29] Small tweaks. --- .../fusesource/slang/scala/deployer/ScalaURLHandler.scala | 8 ++++---- .../slang/scala/deployer/compiler/ScalaCompiler.scala | 4 ++-- .../slang/scala/deployer/parser/ScriptParser.scala | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 8e95df3..90ee22c 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -32,9 +32,9 @@ import org.osgi.framework.BundleContext */ class ScalaURLHandler extends AbstractURLStreamHandlerService { - private var LOG: Log = LogFactory.getLog(classOf[ScalaURLHandler]) - private var PREFIX: String = "scala:" - private var SYNTAX: String = PREFIX + "" + private val LOG: Log = LogFactory.getLog(classOf[ScalaURLHandler]) + private val PREFIX: String = "scala:" + private val SYNTAX: String = PREFIX + "" @BeanProperty var bundleContext : BundleContext = null @@ -74,6 +74,6 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { } } - def connect {} + def connect () {} } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index dfb8eaa..19887a3 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -72,9 +72,9 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val reporter = new AbstractReporter { - def displayPrompt = println("compiler:") + def displayPrompt () { println("compiler:") } - def display(position: Position, msg: String, severity: Severity): Unit = { + def display(position: Position, msg: String, severity: Severity) { LOG.warn(position + ":" + msg) } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala index b4cb797..a47663d 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala @@ -23,7 +23,7 @@ case class Code (code : String) extends Item abstract class Commented extends Item case class Comment (code : String) extends Commented -case class Manifest extends Commented +case class Manifest () extends Commented object ManifestParser extends RegexParsers { From 7de795488efb966206bc15850b8221f458535d5f Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 23 Mar 2012 18:12:18 +0100 Subject: [PATCH 15/29] Using StoreReporter instead of a custom AbstractReporter. --- .../deployer/compiler/ScalaCompiler.scala | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 19887a3..5e783f4 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -19,12 +19,14 @@ */ package org.fusesource.slang.scala.deployer.compiler -import tools.nsc.reporters.AbstractReporter +import tools.nsc.reporters._ import org.apache.commons.logging.LogFactory import tools.nsc.io.{VirtualDirectory, AbstractFile} import tools.nsc.{Global, Settings} import tools.nsc.util._ +class ScalaCompileFailure extends Exception + /** * Scala compiler that uses a provided list of bundles as the compiler * classpath @@ -62,7 +64,15 @@ class ScalaCompiler(bundles: List[AbstractFile]) { e.printStackTrace() throw e } + + /* TODO: We are using the compiler in this bundle, and we access stateful + things, such as reports. Even though, at first glance, things seem local + enough not to worry about threads, we should worry about synchronising + access to the reporter. Even more than that: Accessing the compiler + concurrently inherently seems to be a bad idea. */ + reporter.reset() run.compileFiles (List(source)) + if (reporter.ERROR.count != 0) throw new ScalaCompileFailure () dir @@ -70,7 +80,9 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val settings = new Settings - lazy val reporter = new AbstractReporter { + lazy val reporter = new StoreReporter + +/* lazy val reporter = new AbstractReporter { def displayPrompt () { println("compiler:") } @@ -79,7 +91,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { } val settings = ScalaCompiler.this.settings - } + }*/ lazy val compiler = new Global(settings, reporter) { From 93fd74282c7dd49b8ec03cc65bc56f15530a74ef Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 23 Mar 2012 19:02:27 +0100 Subject: [PATCH 16/29] Trying to implement failing bundles for failed compilation. --- .../slang/scala/deployer/ScalaSource.scala | 11 +- .../slang/scala/deployer/ScrewedSource.scala | 223 ++++++++++++++++++ .../deployer/compiler/ScalaCompiler.scala | 4 +- 3 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index bb21598..723b1ad 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -25,8 +25,7 @@ import org.apache.commons.logging.LogFactory import org.osgi.framework.BundleContext import tools.nsc.io.AbstractFile import tools.nsc.io.PlainFile -import compiler.Bundles -import compiler.ScalaCompiler +import compiler._ import archiver.ScalaArchiver class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends AbstractFile { @@ -134,7 +133,13 @@ class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends Ab def compile () : AbstractFile = { LOG.debug ("Compiling " + this + " using embedded Scala compiler.") - (new ScalaCompiler (libraries)).compile (this) + try { (new ScalaCompiler (libraries)).compile (this) } + catch {case e : ScalaCompileFailure => + // TODO: We here pass the same libs as the AbstractFile. Would + // be nicer to trim down to just what is the needed for the + // error-reporting bundle. But, oh well... + (new ScalaCompiler (libraries)).compile (new ScrewedSource (this)) + } } def archive (dir : AbstractFile) = { diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala new file mode 100644 index 0000000..723bd42 --- /dev/null +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala @@ -0,0 +1,223 @@ +/** + * Copyright (C) Crossing-Tech SA, 2012. + * Contact: + * + * Copyright (C) FuseSource, Inc. + * http://fusesource.com + * + * Licensed 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. + */ +package org.fusesource.slang.scala.deployer + +import java.io._ +/*import java.net.URL*/ +import org.apache.commons.logging.LogFactory +/*import org.osgi.framework.BundleContext*/ +import tools.nsc.io.AbstractFile +/*import tools.nsc.io.PlainFile +import compiler.Bundles +import compiler.ScalaCompiler +import archiver.ScalaArchiver*/ + +class ScrewedSource (var f : AbstractFile) extends AbstractFile { + + final val LOG = LogFactory.getLog(classOf[ScrewedSource]) + + def fail(msg : String) : Nothing = { + val s = "ScrewedSource: " + msg + " unimplemented." + println(s); LOG.debug(s); throw new Exception (s) + } + + override def lookupNameUnchecked (name : String, directory : Boolean) = fail("lookupNameUnchecked") + + override def lookupName (name : String, directory : Boolean) = fail("lookupName") + + override def iterator = fail("iterator") + + override def output = fail("output") + + override def input = new ByteArrayInputStream (""" + + import org.osgi.framework.{BundleContext, BundleActivator} + + package org.fusesource.slang.scala.deployer.failure { + + class MyActivator extends BundleActivator { + + def start (context : BundleContext) { throw new Exception ("Failed to compile Scala code") } + + def stop (context : BundleContext) { } + + } + + } + + """.getBytes) + + override def lastModified = fail("lastModified") + + override def isDirectory = fail("isDirectory") + + override def delete = fail("delete") + + override def create = fail("create") + + override def file = fail("file") + + override def container = fail("container") + + override def absolute = fail("absolute") + + override def path = f.path + + //override def path : String = file.path + + override def name = fail("name") + +} + +/*class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends AbstractFile { + + final val LOG = LogFactory.getLog(classOf[ScalaSource]) + + if ((libraries == null) || libraries.exists(_ == null)) + throw new Exception ("Invalid libraries for ScalaSource constructor.") + + if (url == null) + throw new Exception ("Invalid URL for ScalaSource constructor.") + + def this (url : URL, context : BundleContext) = this (url, + Option(context) match { + case None => + throw new Exception ("No BundleContext available to search for OSGi bundles.") + // TODO: Why not List()? + case Some (ctxt) => + val framework = ctxt.getProperty ("karaf.framework") + val jar = new File ( + ctxt.getProperty ("karaf.base"), + ctxt.getProperty ("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) + } + ) + + /**********************************************************************/ + + /* It should be noted that the Scala compiler has the following piece of + code to read so-called AbstractFiles. See SourceReader.scala, lines + 48 to 59 in the compiler source code. + + def read(file: AbstractFile): Array[Char] = { + try file match { + case p: PlainFile => read(p.file) + case z: ZipArchive#Entry => read(Channels.newChannel(z.input)) + case _ => read(ByteBuffer.wrap(file.toByteArray)) + } + catch { + case e: Exception => reportEncodingError("" + file) ; Array() + } + } + + The big problem about this pattern-matching is that the principle of + a common interface using the "toByteArray" method is invalidated. In + our specific case, this means that it useless to override the input(), + toCharArray() or toByteArray() methods to intercept and rewrite on the + fly what is read from the file. + + We therefore chose not to inherit from the PlainFile, but to prefer + composition over inheritance. Which the reason why we have a plainFile + field: fooling this pattern-matching. */ + + val plainFile : PlainFile = new PlainFile (new File (url.toURI)) + + override def name : String = plainFile.name + + override def path : String = plainFile.path + + override def absolute : AbstractFile = plainFile.absolute + + override def container : AbstractFile = plainFile.container + + override def file : File = plainFile.file + + override def create () : Unit = plainFile.create () + + override def delete () : Unit = plainFile.delete () + + override def isDirectory : Boolean = plainFile.isDirectory + + override def lastModified : Long = plainFile.lastModified + + override def input : InputStream = plainFile.input + + override def toByteArray : Array[Byte] = + + /* NOTE: If the sizeOption is not properly overriden, the AbstractFile + default implementation of sizeOption will blow up. Hence the 'catch'. + + These composition vs. inheritance bugs are hard to find. In case this + happens, continue delegating calls to plainFile. */ + + try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} + + override def output : OutputStream = plainFile.output + + override def sizeOption = plainFile.sizeOption + + override def iterator : Iterator[AbstractFile] = plainFile.iterator + + override def lookupName (name : String, directory : Boolean) : AbstractFile = + plainFile.lookupName (name, directory) + + override def lookupNameUnchecked (name : String, directory : Boolean) : AbstractFile = + plainFile.lookupNameUnchecked (name, directory) + + override def toString () = + /* This call needs to be delegated to ensure that the referenced file is + named properly. The implementation in PlainFile removes the file: URI + prefix that is fed to a ScalaSource instance at construct-time. */ + plainFile.toString + + /**********************************************************************/ + + def compile () : AbstractFile = { + LOG.debug ("Compiling " + this + " using embedded Scala compiler.") + try (new ScalaCompiler (libraries)).compile (this) + catch {case e : ScalaCompileFailure => + (new ScrewedSource).compile + } + } + + def archive (dir : AbstractFile) = { + LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") + (new ScalaArchiver (libraries)).archive (dir, this) + } + + def transform () = { + LOG.info ("Transforming " + this + " into an OSGi bundle.") + manifest () + archive (compile ()) + } + + def manifest () { + + val source = io.Source.fromInputStream(input).getLines().mkString("\n") + //LOG.info ("Manifest: \n" + source) + + import parser.ScriptParser._ + import scala.util.parsing.combinator._ + + val c : ParseResult[List[parser.Item]] = parse(source) + LOG.info("Comment:\n" + c) + /* TODO: Extract manifest from this abstract file. */ + } +}*/ diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 5e783f4..6eb086e 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -25,7 +25,7 @@ import tools.nsc.io.{VirtualDirectory, AbstractFile} import tools.nsc.{Global, Settings} import tools.nsc.util._ -class ScalaCompileFailure extends Exception +class ScalaCompileFailure (path : String) extends Exception ("Slang Scala compiler failed to compile " + path) /** * Scala compiler that uses a provided list of bundles as the compiler @@ -72,7 +72,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { concurrently inherently seems to be a bad idea. */ reporter.reset() run.compileFiles (List(source)) - if (reporter.ERROR.count != 0) throw new ScalaCompileFailure () + if (reporter.ERROR.count != 0) throw new ScalaCompileFailure (source.path) dir From 67744c26a711743dd2515fe97f6248564350bef7 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Fri, 23 Mar 2012 20:28:45 +0100 Subject: [PATCH 17/29] Able to provide a failing bundle when compilation fails. --- .../slang/scala/deployer/ScrewedSource.scala | 173 ++---------------- .../deployer/compiler/ScalaCompiler.scala | 9 +- 2 files changed, 24 insertions(+), 158 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala index 723bd42..aae880f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala @@ -2,9 +2,6 @@ * Copyright (C) Crossing-Tech SA, 2012. * Contact: * - * Copyright (C) FuseSource, Inc. - * http://fusesource.com - * * Licensed 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 @@ -20,19 +17,15 @@ package org.fusesource.slang.scala.deployer import java.io._ -/*import java.net.URL*/ import org.apache.commons.logging.LogFactory -/*import org.osgi.framework.BundleContext*/ import tools.nsc.io.AbstractFile -/*import tools.nsc.io.PlainFile -import compiler.Bundles -import compiler.ScalaCompiler -import archiver.ScalaArchiver*/ class ScrewedSource (var f : AbstractFile) extends AbstractFile { final val LOG = LogFactory.getLog(classOf[ScrewedSource]) + LOG.debug ("ScrewedSource for " + f.path) + def fail(msg : String) : Nothing = { val s = "ScrewedSource: " + msg + " unimplemented." println(s); LOG.debug(s); throw new Exception (s) @@ -46,23 +39,27 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { override def output = fail("output") - override def input = new ByteArrayInputStream (""" + override def sizeOption = Some(code.length) + + def code = """ - import org.osgi.framework.{BundleContext, BundleActivator} + import org.osgi.framework.{BundleContext, BundleActivator} - package org.fusesource.slang.scala.deployer.failure { + package org.fusesource.slang.scala.deployer.failure { - class MyActivator extends BundleActivator { + class MyActivator extends BundleActivator { - def start (context : BundleContext) { throw new Exception ("Failed to compile Scala code") } + def start (context : BundleContext) { throw new Exception ("Failed to compile Scala code") } - def stop (context : BundleContext) { } + def stop (context : BundleContext) { } - } + } - } + } - """.getBytes) + """.getBytes("UTF-8") + + override def input = new ByteArrayInputStream(code) override def lastModified = fail("lastModified") @@ -80,144 +77,6 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { override def path = f.path - //override def path : String = file.path - - override def name = fail("name") + override def name = f.name } - -/*class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends AbstractFile { - - final val LOG = LogFactory.getLog(classOf[ScalaSource]) - - if ((libraries == null) || libraries.exists(_ == null)) - throw new Exception ("Invalid libraries for ScalaSource constructor.") - - if (url == null) - throw new Exception ("Invalid URL for ScalaSource constructor.") - - def this (url : URL, context : BundleContext) = this (url, - Option(context) match { - case None => - throw new Exception ("No BundleContext available to search for OSGi bundles.") - // TODO: Why not List()? - case Some (ctxt) => - val framework = ctxt.getProperty ("karaf.framework") - val jar = new File ( - ctxt.getProperty ("karaf.base"), - ctxt.getProperty ("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) - } - ) - - /**********************************************************************/ - - /* It should be noted that the Scala compiler has the following piece of - code to read so-called AbstractFiles. See SourceReader.scala, lines - 48 to 59 in the compiler source code. - - def read(file: AbstractFile): Array[Char] = { - try file match { - case p: PlainFile => read(p.file) - case z: ZipArchive#Entry => read(Channels.newChannel(z.input)) - case _ => read(ByteBuffer.wrap(file.toByteArray)) - } - catch { - case e: Exception => reportEncodingError("" + file) ; Array() - } - } - - The big problem about this pattern-matching is that the principle of - a common interface using the "toByteArray" method is invalidated. In - our specific case, this means that it useless to override the input(), - toCharArray() or toByteArray() methods to intercept and rewrite on the - fly what is read from the file. - - We therefore chose not to inherit from the PlainFile, but to prefer - composition over inheritance. Which the reason why we have a plainFile - field: fooling this pattern-matching. */ - - val plainFile : PlainFile = new PlainFile (new File (url.toURI)) - - override def name : String = plainFile.name - - override def path : String = plainFile.path - - override def absolute : AbstractFile = plainFile.absolute - - override def container : AbstractFile = plainFile.container - - override def file : File = plainFile.file - - override def create () : Unit = plainFile.create () - - override def delete () : Unit = plainFile.delete () - - override def isDirectory : Boolean = plainFile.isDirectory - - override def lastModified : Long = plainFile.lastModified - - override def input : InputStream = plainFile.input - - override def toByteArray : Array[Byte] = - - /* NOTE: If the sizeOption is not properly overriden, the AbstractFile - default implementation of sizeOption will blow up. Hence the 'catch'. - - These composition vs. inheritance bugs are hard to find. In case this - happens, continue delegating calls to plainFile. */ - - try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} - - override def output : OutputStream = plainFile.output - - override def sizeOption = plainFile.sizeOption - - override def iterator : Iterator[AbstractFile] = plainFile.iterator - - override def lookupName (name : String, directory : Boolean) : AbstractFile = - plainFile.lookupName (name, directory) - - override def lookupNameUnchecked (name : String, directory : Boolean) : AbstractFile = - plainFile.lookupNameUnchecked (name, directory) - - override def toString () = - /* This call needs to be delegated to ensure that the referenced file is - named properly. The implementation in PlainFile removes the file: URI - prefix that is fed to a ScalaSource instance at construct-time. */ - plainFile.toString - - /**********************************************************************/ - - def compile () : AbstractFile = { - LOG.debug ("Compiling " + this + " using embedded Scala compiler.") - try (new ScalaCompiler (libraries)).compile (this) - catch {case e : ScalaCompileFailure => - (new ScrewedSource).compile - } - } - - def archive (dir : AbstractFile) = { - LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") - (new ScalaArchiver (libraries)).archive (dir, this) - } - - def transform () = { - LOG.info ("Transforming " + this + " into an OSGi bundle.") - manifest () - archive (compile ()) - } - - def manifest () { - - val source = io.Source.fromInputStream(input).getLines().mkString("\n") - //LOG.info ("Manifest: \n" + source) - - import parser.ScriptParser._ - import scala.util.parsing.combinator._ - - val c : ParseResult[List[parser.Item]] = parse(source) - LOG.info("Comment:\n" + c) - /* TODO: Extract manifest from this abstract file. */ - } -}*/ diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 6eb086e..735e603 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -80,7 +80,14 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val settings = new Settings - lazy val reporter = new StoreReporter + lazy val reporter = new StoreReporter { + + override def info0 (pos: Position, msg: String, severity: Severity, force: Boolean) { + LOG.warn(pos + ":" + msg) + super.info0(pos, msg: String, severity, force) + } + + } /* lazy val reporter = new AbstractReporter { From 2462b898e8d1ee2fa81f412d667070a8b4cf995f Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Mon, 26 Mar 2012 15:30:17 +0200 Subject: [PATCH 18/29] Safer generation of bundles. --- .../slang/scala/deployer/ScrewedSource.scala | 3 +- .../deployer/archiver/ScalaArchiver.scala | 62 ++++++++++++------- .../scala/deployer/compiler/Bundles.scala | 28 ++++----- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala index aae880f..adec69d 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala @@ -57,7 +57,8 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { } - """.getBytes("UTF-8") + """.getBytes("UTF-8") // TODO: Check if global.settings.encoding.value is not better. + // see line 77 of AbstractFile.scala in the compiler's source code. override def input = new ByteArrayInputStream(code) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index 8f9cd2a..304cb8f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -38,25 +38,35 @@ class ScalaArchiver(bundles: List[AbstractFile]) { val LOG = LogFactory.getLog(classOf[ScalaArchiver]) + // classloaders contains a classloader supposed to be able to load classes + // from a given bundles. In fact, one classloader for each bundle. val classloaders = bundles.map(new AbstractFileClassLoader(_, getClass.getClassLoader)) def archive(dir: AbstractFile, source: ScalaSource) : InputStream = { - val classloader = createClassLoader(dir) + + println("Archiving " + source) + + val classloader : AbstractFileClassLoader = createClassLoader(dir) val props = new Properties val bytes = new ByteArrayOutputStream val jar = new JarOutputStream(bytes) entries(dir) { (name: String, file: AbstractFile) => + println("Archiving - name: " + name + ", file:" + file) archiveFile(file, jar, name) try { - val theType = classloader.loadClass(name.replaceAll(".class", "").replaceAll("/", ".")) + val renaming = name.replaceAll(".class", "").replaceAll("/", ".") + // TODO: Name processing is a bit crude... should be cleaned up. + println("Renaming name " + name + " in " + renaming) + val theType = classloader.loadClass(renaming) if (classOf[BundleActivator].isAssignableFrom(theType)) { LOG.debug("Discovered bundle activator " + theType.getName) props.put("Bundle-Activator", theType.getName) } - } catch { - case e: Exception => e.printStackTrace + } catch { case e: Exception => + println ("Exception caught... while processing " + name) + e.printStackTrace } } @@ -73,10 +83,13 @@ class ScalaArchiver(bundles: List[AbstractFile]) { def entries(dir: AbstractFile, path:String)(action: (String, AbstractFile) => Unit) : Unit = { dir.foreach { (file: AbstractFile) => + println("Iterating through compiled files: " + file) val name = if (path.length == 0) { file.name } else { path + "/" + file.name } if (file.isDirectory) { + println (" File is a directory.") entries(file, name)(action) } else { + println (" File is not a directory.") action(name, file) } } @@ -107,28 +120,35 @@ class ScalaArchiver(bundles: List[AbstractFile]) { } def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, getClass.getClassLoader) { - override def findClass(name: String) : Class[_] = { - try { - // let's try the bundle we're generating first - super.findClass(name) - } catch { - // and then fall back to the rest of the bundles - case e: ClassNotFoundException => findClassInBundles(name) - } + + // Set to true to trace classloader activity. + override protected def trace = true + + override def findClass(name: String) : Class[_] = try { + println ("We are trying to find the class " + name) + // let's try the bundle we're generating first + super.findClass(name) + } catch { case e : ClassNotFoundException => + println ("The class " + name + " could not be found.") + // and then fall back to the rest of the bundles + findClassInBundles(name) } - def findClassInBundles(name: String) : Class[_] = { + def findClassInBundles(name: String) : Class[_] = classloaders.map(cl => findClass(name, cl)).find(cls => cls.isDefined) match { - case Some(cls) => cls.get - case None => throw new ClassNotFoundException(name) + case Some(cls) => println ("FOUND!!!!!"); cls.get + case None => println ("NOT FOUND!!!!"); throw new ClassNotFoundException(name) } - } def findClass(name: String, loader: AbstractFileClassLoader) = - try { - Some(loader.findClass(name)) - } catch { - case e: ClassNotFoundException => None - } + try { println ("Trying to find " + name + " in some custom bundle.") + Some(loader.findClass(name)) + } catch { case e: /* ClassNotFoundException */ Exception => + /* TODO: Original code was catching the ClassNotFoundException, + and an inadequate exception was falling through. So I widened + the range of caught exceptions, but this is only a workaround. */ + println ("But wasn't found...") + None + } } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index 05198d4..63842bb 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -169,31 +169,31 @@ object Bundles { * If a bundle has a file: URL, a {@PlainFile} is being used, otherwise w */ def create(bundles: Array[Bundle]) : List[AbstractFile] = { + println(bundles.length) var result : List[AbstractFile] = List() for (bundle <- bundles; val index = bundles.indexOf(bundle)) { - var url = bundle.getResource("/"); + var url = bundle.getResource("/") if (url == null) { - url = bundle.getResource(""); + url = bundle.getResource("") } if (url != null) { if ("file" == url.getProtocol()) { - try { - result = new PlainFile(new File(url.toURI())) :: result; + try { println("Packing bundle as PlainFile: " + bundle.getSymbolicName()) + result = new PlainFile(new File(url.toURI())) :: result + } catch { case e: URISyntaxException => + println("Failed to pack bundle: " + bundle.getSymbolicName()) + throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) } - catch { - case e: URISyntaxException => throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e); - } - } - else { - result = Bundles.create(bundle) :: result; + } else { + println("Packing bundle as DirEntry: " + bundle.getSymbolicName()) + result = Bundles.create(bundle) :: result } - } - else { - LOG.warn("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName()); + } else { + println("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName()) } } - result; + result } From 0f1ac8e7a2b2b19c86a7e5172cd712b318e7f555 Mon Sep 17 00:00:00 2001 From: Carlo Jelmini Date: Tue, 27 Mar 2012 13:05:03 +0200 Subject: [PATCH 19/29] Review: essentially simple refactorings --- .../slang/scala/deployer/ScalaSource.scala | 198 +++++++++--------- .../scala/deployer/ScalaURLHandler.scala | 2 +- .../slang/scala/deployer/ScrewedSource.scala | 11 +- .../deployer/archiver/ScalaArchiver.scala | 122 +++++------ .../scala/deployer/compiler/Bundles.scala | 161 +++++++------- .../scala/deployer/ScalaTransformerTest.scala | 13 +- 6 files changed, 263 insertions(+), 244 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 723b1ad..b7b0dda 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -9,7 +9,7 @@ * 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 + * 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, @@ -28,141 +28,137 @@ import tools.nsc.io.PlainFile import compiler._ import archiver.ScalaArchiver -class ScalaSource (val url : URL, val libraries : List[AbstractFile]) extends AbstractFile { +class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends AbstractFile { - final val LOG = LogFactory.getLog(classOf[ScalaSource]) + final val LOG = LogFactory.getLog(classOf[ScalaSource]) - if ((libraries == null) || libraries.exists(_ == null)) - throw new Exception ("Invalid libraries for ScalaSource constructor.") + require(url != null, "Invalid URL for ScalaSource constructor.") + require((libraries != null) && libraries.forall(_ != null), "Invalid libraries for ScalaSource constructor.") - if (url == null) - throw new Exception ("Invalid URL for ScalaSource constructor.") + def this(url: URL, context: BundleContext) = this(url, Option(context) match { + case None => + throw new IllegalArgumentException("No BundleContext available to search for OSGi bundles.") + // TODO: Why not List()? + case Some(ctxt) => + val framework = ctxt.getProperty("karaf.framework") + val jar = new File( + ctxt.getProperty("karaf.base"), + ctxt.getProperty("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create(ctxt.getBundles) + } + ) - def this (url : URL, context : BundleContext) = this (url, - Option(context) match { - case None => - throw new Exception ("No BundleContext available to search for OSGi bundles.") - // TODO: Why not List()? - case Some (ctxt) => - val framework = ctxt.getProperty ("karaf.framework") - val jar = new File ( - ctxt.getProperty ("karaf.base"), - ctxt.getProperty ("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create (ctxt.getBundles) - } - ) + /**********************************************************************/ - /**********************************************************************/ + /* It should be noted that the Scala compiler has the following piece of + code to read so-called AbstractFiles. See SourceReader.scala, lines + 48 to 59 in the compiler source code. - /* It should be noted that the Scala compiler has the following piece of - code to read so-called AbstractFiles. See SourceReader.scala, lines - 48 to 59 in the compiler source code. + def read(file: AbstractFile): Array[Char] = { + try file match { + case p: PlainFile => read(p.file) + case z: ZipArchive#Entry => read(Channels.newChannel(z.input)) + case _ => read(ByteBuffer.wrap(file.toByteArray)) + } + catch { + case e: Exception => reportEncodingError("" + file) ; Array() + } + } - def read(file: AbstractFile): Array[Char] = { - try file match { - case p: PlainFile => read(p.file) - case z: ZipArchive#Entry => read(Channels.newChannel(z.input)) - case _ => read(ByteBuffer.wrap(file.toByteArray)) - } - catch { - case e: Exception => reportEncodingError("" + file) ; Array() - } - } + The big problem about this pattern-matching is that the principle of + a common interface using the "toByteArray" method is invalidated. In + our specific case, this means that it useless to override the input(), + toCharArray() or toByteArray() methods to intercept and rewrite on the + fly what is read from the file. - The big problem about this pattern-matching is that the principle of - a common interface using the "toByteArray" method is invalidated. In - our specific case, this means that it useless to override the input(), - toCharArray() or toByteArray() methods to intercept and rewrite on the - fly what is read from the file. + We therefore chose not to inherit from the PlainFile, but to prefer + composition over inheritance. Which the reason why we have a plainFile + field: fooling this pattern-matching. */ - We therefore chose not to inherit from the PlainFile, but to prefer - composition over inheritance. Which the reason why we have a plainFile - field: fooling this pattern-matching. */ + val plainFile: PlainFile = new PlainFile(new File(url.toURI)) - val plainFile : PlainFile = new PlainFile (new File (url.toURI)) + override def name: String = plainFile.name - override def name : String = plainFile.name + override def path: String = plainFile.path - override def path : String = plainFile.path + override def absolute: AbstractFile = plainFile.absolute - override def absolute : AbstractFile = plainFile.absolute + override def container: AbstractFile = plainFile.container - override def container : AbstractFile = plainFile.container + override def file: File = plainFile.file - override def file : File = plainFile.file + override def create(): Unit = plainFile.create() - override def create () : Unit = plainFile.create () + override def delete(): Unit = plainFile.delete() - override def delete () : Unit = plainFile.delete () + override def isDirectory: Boolean = plainFile.isDirectory - override def isDirectory : Boolean = plainFile.isDirectory + override def lastModified: Long = plainFile.lastModified - override def lastModified : Long = plainFile.lastModified + override def input: InputStream = plainFile.input - override def input : InputStream = plainFile.input + override def toByteArray: Array[Byte] = - override def toByteArray : Array[Byte] = + /* NOTE: If the sizeOption is not properly overriden, the AbstractFile + default implementation of sizeOption will blow up. Hence the 'catch'. - /* NOTE: If the sizeOption is not properly overriden, the AbstractFile - default implementation of sizeOption will blow up. Hence the 'catch'. + These composition vs. inheritance bugs are hard to find. In case this + happens, continue delegating calls to plainFile. */ - These composition vs. inheritance bugs are hard to find. In case this - happens, continue delegating calls to plainFile. */ + try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} - try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} - - override def output : OutputStream = plainFile.output + override def output: OutputStream = plainFile.output - override def sizeOption = plainFile.sizeOption + override def sizeOption = plainFile.sizeOption - override def iterator : Iterator[AbstractFile] = plainFile.iterator + override def iterator: Iterator[AbstractFile] = plainFile.iterator - override def lookupName (name : String, directory : Boolean) : AbstractFile = - plainFile.lookupName (name, directory) + override def lookupName(name: String, directory: Boolean): AbstractFile = + plainFile.lookupName(name, directory) - override def lookupNameUnchecked (name : String, directory : Boolean) : AbstractFile = - plainFile.lookupNameUnchecked (name, directory) + override def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile = + plainFile.lookupNameUnchecked(name, directory) - override def toString () = - /* This call needs to be delegated to ensure that the referenced file is - named properly. The implementation in PlainFile removes the file: URI - prefix that is fed to a ScalaSource instance at construct-time. */ - plainFile.toString + override def toString() = + /* This call needs to be delegated to ensure that the referenced file is + named properly. The implementation in PlainFile removes the file: URI + prefix that is fed to a ScalaSource instance at construct-time. */ + plainFile.toString - /**********************************************************************/ + /**********************************************************************/ - def compile () : AbstractFile = { - LOG.debug ("Compiling " + this + " using embedded Scala compiler.") - try { (new ScalaCompiler (libraries)).compile (this) } - catch {case e : ScalaCompileFailure => - // TODO: We here pass the same libs as the AbstractFile. Would - // be nicer to trim down to just what is the needed for the - // error-reporting bundle. But, oh well... - (new ScalaCompiler (libraries)).compile (new ScrewedSource (this)) - } - } + def compile(): AbstractFile = { + LOG.debug("Compiling " + this + " using embedded Scala compiler.") + try {(new ScalaCompiler(libraries)).compile(this)} + catch { + case e: ScalaCompileFailure => + // TODO: We here pass the same libs as the AbstractFile. Would + // be nicer to trim down to just what is the needed for the + // error-reporting bundle. But, oh well... + (new ScalaCompiler(libraries)).compile(new ScrewedSource(this)) + } + } - def archive (dir : AbstractFile) = { - LOG.debug ("Archiving compiled " + this + " into an OSGi bundle.") - (new ScalaArchiver (libraries)).archive (dir, this) - } + def archive(dir: AbstractFile) = { + LOG.debug("Archiving compiled " + this + " into an OSGi bundle.") + (new ScalaArchiver(libraries)).archive(dir, this) + } - def transform () = { - LOG.info ("Transforming " + this + " into an OSGi bundle.") - manifest () - archive (compile ()) - } + def transform() = { + LOG.info("Transforming " + this + " into an OSGi bundle.") + manifest() + archive(compile()) + } - def manifest () { + def manifest() { - val source = io.Source.fromInputStream(input).getLines().mkString("\n") - //LOG.info ("Manifest: \n" + source) + val source = io.Source.fromInputStream(input).getLines().mkString("\n") + //LOG.info ("Manifest: \n" + source) - import parser.ScriptParser._ - import scala.util.parsing.combinator._ + import parser.ScriptParser._ - val c : ParseResult[List[parser.Item]] = parse(source) - LOG.info("Comment:\n" + c) - /* TODO: Extract manifest from this abstract file. */ - } + val c: ParseResult[List[parser.Item]] = parse(source) +// LOG.info("Comment:\n" + c) + /* TODO: Extract manifest from this abstract file. */ + } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 90ee22c..213b388 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -69,7 +69,7 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { catch { case e: Exception => { LOG.error("Error creating bundle from Scala source code", e) - throw new IOException("Error opening spring xml url").initCause(e).asInstanceOf[IOException] + throw e } } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala index adec69d..fec1626 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala @@ -28,7 +28,8 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { def fail(msg : String) : Nothing = { val s = "ScrewedSource: " + msg + " unimplemented." - println(s); LOG.debug(s); throw new Exception (s) + LOG.debug(s) + throw new Exception(s) } override def lookupNameUnchecked (name : String, directory : Boolean) = fail("lookupNameUnchecked") @@ -39,6 +40,10 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { override def output = fail("output") + /* sizeOption needs to be overriden to provide the length of the input stream. + It is NOT declared abstract in AbstractFile, which leads to weird IO errors + if this override is not properly made. + */ override def sizeOption = Some(code.length) def code = """ @@ -66,9 +71,9 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { override def isDirectory = fail("isDirectory") - override def delete = fail("delete") + override def delete() { fail("delete")} - override def create = fail("create") + override def create() { fail("create")} override def file = fail("file") diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index 304cb8f..f5bc698 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -9,7 +9,7 @@ * 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 + * 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, @@ -42,57 +42,54 @@ class ScalaArchiver(bundles: List[AbstractFile]) { // from a given bundles. In fact, one classloader for each bundle. val classloaders = bundles.map(new AbstractFileClassLoader(_, getClass.getClassLoader)) - def archive(dir: AbstractFile, source: ScalaSource) : InputStream = { + def archive(dir: AbstractFile, source: ScalaSource): InputStream = { - println("Archiving " + source) - - val classloader : AbstractFileClassLoader = createClassLoader(dir) + val classloader: AbstractFileClassLoader = createClassLoader(dir) val props = new Properties val bytes = new ByteArrayOutputStream val jar = new JarOutputStream(bytes) - entries(dir) { (name: String, file: AbstractFile) => - println("Archiving - name: " + name + ", file:" + file) - archiveFile(file, jar, name) - try { - val renaming = name.replaceAll(".class", "").replaceAll("/", ".") - // TODO: Name processing is a bit crude... should be cleaned up. - println("Renaming name " + name + " in " + renaming) - val theType = classloader.loadClass(renaming) - if (classOf[BundleActivator].isAssignableFrom(theType)) { - LOG.debug("Discovered bundle activator " + theType.getName) - props.put("Bundle-Activator", theType.getName) + entries(dir) { + (name: String, file: AbstractFile) => + archiveFile(file, jar, name) + try { + val renaming = name.replaceAll(".class", "").replaceAll("/", ".") + // TODO: Name processing is a bit crude... should be cleaned up. + val theType = classloader.loadClass(renaming) + if (classOf[BundleActivator].isAssignableFrom(theType)) { + LOG.debug("Discovered bundle activator " + theType.getName) + props.put("Bundle-Activator", theType.getName) + } + } catch { + case e: Exception => e.printStackTrace() } - } catch { case e: Exception => - println ("Exception caught... while processing " + name) - e.printStackTrace - } - } - jar.close - bytes.close + jar.close() + bytes.close() - createBundle(new ByteArrayInputStream(bytes.toByteArray), - props, bsn(source.url)) + createBundle(new ByteArrayInputStream(bytes.toByteArray), props, bsn(source.url)) } - - def entries(dir: AbstractFile)(action: (String, AbstractFile) => Unit) : Unit = + + def entries(dir: AbstractFile)(action: (String, AbstractFile) => Unit): Unit = entries(dir, "")(action) - def entries(dir: AbstractFile, path:String)(action: (String, AbstractFile) => Unit) : Unit = { - dir.foreach { (file: AbstractFile) => - println("Iterating through compiled files: " + file) - val name = if (path.length == 0) { file.name } else { path + "/" + file.name } - if (file.isDirectory) { - println (" File is a directory.") - entries(file, name)(action) - } else { - println (" File is not a directory.") - action(name, file) - } - } + def entries(dir: AbstractFile, path: String)(action: (String, AbstractFile) => Unit): Unit = { + dir.foreach { + (file: AbstractFile) => + println("Iterating through compiled files: " + file) + val name = if (path.length == 0) {file.name} + else {path + "/" + file.name} + if (file.isDirectory) { + println(" File is a directory.") + entries(file, name)(action) + } + else { + println(" File is not a directory.") + action(name, file) + } + } } def archiveFile(file: AbstractFile, jar: JarOutputStream, name: String) = { @@ -105,7 +102,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { jar.write(bytes, 0, read) read = is.read(bytes) } - jar.closeEntry + jar.closeEntry() } def bsn(url: URL) = { @@ -116,7 +113,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { if (result.startsWith("/")) { result = result.substring(1) } - result.replaceAll("/", ".") + result.replaceAll("/", ".") } def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, getClass.getClassLoader) { @@ -124,31 +121,34 @@ class ScalaArchiver(bundles: List[AbstractFile]) { // Set to true to trace classloader activity. override protected def trace = true - override def findClass(name: String) : Class[_] = try { - println ("We are trying to find the class " + name) - // let's try the bundle we're generating first - super.findClass(name) - } catch { case e : ClassNotFoundException => - println ("The class " + name + " could not be found.") - // and then fall back to the rest of the bundles - findClassInBundles(name) + override def findClass(name: String): Class[_] = try { + println("We are trying to find the class " + name) + // let's try the bundle we're generating first + super.findClass(name) + } catch { + case e: ClassNotFoundException => + println("The class " + name + " could not be found.") + // and then fall back to the rest of the bundles + findClassInBundles(name) } - def findClassInBundles(name: String) : Class[_] = + def findClassInBundles(name: String): Class[_] = classloaders.map(cl => findClass(name, cl)).find(cls => cls.isDefined) match { - case Some(cls) => println ("FOUND!!!!!"); cls.get - case None => println ("NOT FOUND!!!!"); throw new ClassNotFoundException(name) + case Some(cls) => println("FOUND!!!!!"); cls.get + case None => println("NOT FOUND!!!!"); throw new ClassNotFoundException(name) } def findClass(name: String, loader: AbstractFileClassLoader) = - try { println ("Trying to find " + name + " in some custom bundle.") - Some(loader.findClass(name)) - } catch { case e: /* ClassNotFoundException */ Exception => - /* TODO: Original code was catching the ClassNotFoundException, - and an inadequate exception was falling through. So I widened - the range of caught exceptions, but this is only a workaround. */ - println ("But wasn't found...") - None - } + try { + println("Trying to find " + name + " in some custom bundle.") + Some(loader.findClass(name)) + } catch { + case e: /* ClassNotFoundException */ Exception => + /* TODO: Original code was catching the ClassNotFoundException, + and an inadequate exception was falling through. So I widened + the range of caught exceptions, but this is only a workaround. */ + println("But wasn't found...") + None + } } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index 63842bb..d5fb39c 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -9,7 +9,7 @@ * 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 + * 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, @@ -37,10 +37,10 @@ object Bundles { abstract class BundleEntry(url: URL, parent: DirEntry) extends AbstractFile { require(url != null, "url must not be null") - val bundle : Bundle + val bundle: Bundle lazy val (path: String, name: String) = getPathAndName(url) - lazy val fullName: String = (path::name::Nil).filter(!_.isEmpty).mkString("/") + lazy val fullName: String = (path :: name :: Nil).filter(!_.isEmpty).mkString("/") /** * @return null @@ -51,12 +51,12 @@ object Bundles { * @return last modification time or 0 if not known */ def lastModified: Long = - try { url.openConnection.getLastModified } - catch { case _ => 0 } + try {url.openConnection.getLastModified} + catch {case _ => 0} @throws(classOf[IOException]) def container: AbstractFile = Option(parent).getOrElse( - throw new IOException ("No container")) + throw new IOException("No container")) @throws(classOf[IOException]) def input: InputStream = url.openStream() @@ -71,77 +71,86 @@ object Bundles { private def getPathAndName(url: URL): (String, String) = { val u = url.getPath var k = u.length - while( (k > 0) && (u(k - 1) == '/') ) + while ((k > 0) && (u(k - 1) == '/')) k = k - 1 var j = k - while( (j > 0) && (u(j - 1) != '/') ) + while ((j > 0) && (u(j - 1) != '/')) j = j - 1 (u.substring(if (j > 0) 1 else 0, if (j > 1) j - 1 else j), u.substring(j, k)) } - override def toString = fullName + override def toString() = fullName } - class DirEntry(val bundle: Bundle, url: URL, parent: DirEntry) extends BundleEntry(url, parent) { + class DirEntry(val bundle: Bundle, bundleUrl: URL, parent: DirEntry) extends BundleEntry(bundleUrl, parent) { /** * @return true */ def isDirectory: Boolean = true - override def elements : Iterator[AbstractFile] = { - - @tailrec - def removeTrailingSlash(s: String): String = - if (s == null || s.length == 0) - s - else if (s.last == '/') - removeTrailingSlash(s.substring(0, s.length - 1)) - else - s - - import scala.collection.JavaConverters._ - bundle.getEntryPaths(fullName).asScala.map { - case entry : String => { - val entryUrl = Option(Option(bundle.getResource("/" + entry)). - // Bundle.getReource seems to be inconsistent with respect to requiring - // a trailing slash. - getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) - entryUrl match { - case None => - throw new IllegalStateException ("For some reason, OSGi will not let use the entry " + entry) - case Some(url) => - if (entry.endsWith(".class")) - new FileEntry(bundle, url, DirEntry.this) - else new DirEntry(bundle, url, DirEntry.this) - } - } - case _ => - throw new ClassCastException("Items other than Strings found in an OSGi bundle's entry paths.") - } + override def elements: Iterator[AbstractFile] = { + + @tailrec + def removeTrailingSlash(s: String): String = + if (s == null || s.length == 0) { + s + } + else if (s.last == '/') { + removeTrailingSlash(s.substring(0, s.length - 1)) + } + else { + s + } + + import scala.collection.JavaConverters._ + bundle.getEntryPaths(fullName).asScala.map { + case entry: String => { + val entryUrl = Option(Option(bundle.getResource("/" + entry)). + // Bundle.getReource seems to be inconsistent with respect to requiring + // a trailing slash. + getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) + entryUrl match { + case None => + throw new IllegalStateException("For some reason, OSGi will not let use the entry " + entry) + case Some(url) => + if (entry.endsWith(".class")) { + new FileEntry(bundle, url, DirEntry.this) + } + else { + new DirEntry(bundle, url, DirEntry.this) + } + } + } + case _ => + throw new ClassCastException("Items other than Strings found in an OSGi bundle's entry paths.") + } } def lookupName(name: String, directory: Boolean): AbstractFile = { val entry = bundle.getEntry(fullName + "/" + name) Option(entry) match { case None => null - case Some (_) if directory => - new DirEntry (bundle, entry, DirEntry.this) - case Some (_) => - new FileEntry (bundle, entry, DirEntry.this) + case Some(_) if directory => + new DirEntry(bundle, entry, DirEntry.this) + case Some(_) => + new FileEntry(bundle, entry, DirEntry.this) } } override def lookupPathUnchecked(path: String, directory: Boolean) = lookupPath(path, directory) + def lookupNameUnchecked(name: String, directory: Boolean) = lookupName(path, directory) def iterator = elements def absolute = unsupported("absolute() is unsupported") - def create = unsupported("create() is unsupported") - def delete = unsupported("create() is unsupported") + + def create() {unsupported("create() is unsupported")} + + def delete() {unsupported("create() is unsupported")} } class FileEntry(val bundle: Bundle, url: URL, parent: DirEntry) extends BundleEntry(url, parent) { @@ -150,55 +159,65 @@ object Bundles { * @return false */ def isDirectory: Boolean = false - override def sizeOption: Option[Int] = Some(bundle.getEntry(fullName).openConnection().getContentLength()) + + override def sizeOption: Option[Int] = Some(bundle.getEntry(fullName).openConnection().getContentLength) + override def elements: Iterator[AbstractFile] = Iterator.empty + def lookupName(name: String, directory: Boolean): AbstractFile = null override def lookupPathUnchecked(path: String, directory: Boolean) = lookupPath(path, directory) + def lookupNameUnchecked(name: String, directory: Boolean) = lookupName(path, directory) def iterator = elements def absolute = unsupported("absolute() is unsupported") - def create = unsupported("create() is unsupported") - def delete = unsupported("create() is unsupported") + + def create() { + unsupported("create() is unsupported") + } + + def delete() { + unsupported("create() is unsupported") + } } /** * Create an array of {@link AbstractFile}s for a given array of bundles. * If a bundle has a file: URL, a {@PlainFile} is being used, otherwise w */ - def create(bundles: Array[Bundle]) : List[AbstractFile] = { - println(bundles.length) - var result : List[AbstractFile] = List() + def create(bundles: Array[Bundle]): List[AbstractFile] = { + var result: List[AbstractFile] = List() for (bundle <- bundles; val index = bundles.indexOf(bundle)) { - var url = bundle.getResource("/") - if (url == null) { - url = bundle.getResource("") - } + var url = bundle.getResource("/") + if (url == null) { + url = bundle.getResource("") + } - if (url != null) { - if ("file" == url.getProtocol()) { - try { println("Packing bundle as PlainFile: " + bundle.getSymbolicName()) - result = new PlainFile(new File(url.toURI())) :: result - } catch { case e: URISyntaxException => - println("Failed to pack bundle: " + bundle.getSymbolicName()) - throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) - } - } else { - println("Packing bundle as DirEntry: " + bundle.getSymbolicName()) - result = Bundles.create(bundle) :: result - } - } else { - println("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName()) + if (url != null) { + if ("file" == url.getProtocol) { + try { + result = new PlainFile(new File(url.toURI)) :: result + } catch { + case e: URISyntaxException => + throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) + } + } + else { + result = Bundles.create(bundle) :: result } + } + else { + LOG.warn("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName); + } } result } /** - * Create a new { @link AbstractFile } instance representing an + * Create a new { @link AbstractFile } instance representing an * { @link org.osgi.framework.Bundle } * * @param bundle the bundle diff --git a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala index 8494dbe..2824a54 100644 --- a/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala +++ b/scala/deployer/src/test/scala/org/fusesource/slang/scala/deployer/ScalaTransformerTest.scala @@ -22,9 +22,8 @@ package org.fusesource.slang.scala.deployer import org.junit.{Before, Test} import org.junit.Assert.{assertNotNull,assertTrue,assertEquals} import java.util.jar.JarInputStream -import java.io.{ByteArrayInputStream, FileOutputStream, ByteArrayOutputStream, File} +import java.io.File import tools.nsc.io.AbstractFile -import org.osgi.framework.BundleContext /** * Test cases for {@link ScalaTransformer} @@ -41,13 +40,13 @@ class ScalaTransformerTest { } @Before - def createTransformer = { + def createTransformer() { val scalaLib = new File (repository, "org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar") libraries = List (AbstractFile.getFile(scalaLib)) } @Test - def testCompile = { + def testCompile() { val source = new ScalaSource (this.getClass.getClassLoader.getResource ("SimpleTest.scala"), libraries) val result = source.compile () @@ -56,7 +55,7 @@ class ScalaTransformerTest { } @Test - def testTransform = { + def testTransform() { val source = new ScalaSource (this.getClass.getClassLoader.getResource("SimpleTest.scala"), libraries) val result = source.transform () var jar = new JarInputStream (result) @@ -66,7 +65,7 @@ class ScalaTransformerTest { } @Test - def testTransformWithActivator = { + def testTransformWithActivator() { val source = new ScalaSource (this.getClass.getClassLoader.getResource ("TestWithActivator.scala"), libraries) val result = source.transform () var jar = new JarInputStream (result) @@ -77,7 +76,7 @@ class ScalaTransformerTest { assertEquals ("BundleActivator class should have been automatically detected", "org.test.TestWithActivator", manifest.getMainAttributes.getValue ("Bundle-Activator")) assertTrue ("Bundle-SymbolicName should have a decent value", - manifest.getMainAttributes().getValue("Bundle-SymbolicName").endsWith("TestWithActivator")); + manifest.getMainAttributes.getValue("Bundle-SymbolicName").endsWith("TestWithActivator")); } From 92430e4891635c40f9a3ff545ecdce0ee941b69a Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 15:23:33 +0200 Subject: [PATCH 20/29] Refactoring, and adding an exception reporting mechanism to embedded compiler. --- .../deployer/ScalaDeploymentListener.scala | 17 +-- .../slang/scala/deployer/ScalaSource.scala | 107 +++++++++--------- .../scala/deployer/ScalaURLHandler.scala | 28 ++--- .../slang/scala/deployer/ScrewedSource.scala | 64 +++++------ .../deployer/archiver/ScalaArchiver.scala | 29 ++--- .../scala/deployer/compiler/Bundles.scala | 77 ++++--------- .../deployer/compiler/ScalaCompiler.scala | 19 +--- .../deployer/compiler/VirtualDirectory.scala | 88 -------------- .../scala/deployer/parser/ScriptParser.scala | 59 +++++----- .../test/resources/TestWithActivator.scala | 2 +- 10 files changed, 158 insertions(+), 332 deletions(-) delete mode 100644 scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/VirtualDirectory.scala diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala index 57e210c..279ca9f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaDeploymentListener.scala @@ -32,18 +32,9 @@ class ScalaDeploymentListener extends ArtifactUrlTransformer { val LOG = LogFactory.getLog(classOf[ScalaDeploymentListener]) - def canHandle(artifact: File) = { - artifact.isFile && artifact.getName.endsWith(".scala") - } + def canHandle(artifact: File) = artifact.isFile && artifact.getName.endsWith(".scala") - def transform(artifact: URL) : URL = { - try { - new URL("scala", null, artifact.toString) - } catch { - case e: Exception => { - LOG.error("Unable to build scala bundle", e) - null - } - } + def transform(artifact: URL) : URL = try new URL("scala", null, artifact.toString) catch { + case e: Exception => LOG.error("Unable to build scala bundle", e); null } -} \ No newline at end of file +} diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index b7b0dda..7a5260e 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -35,18 +35,12 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr require(url != null, "Invalid URL for ScalaSource constructor.") require((libraries != null) && libraries.forall(_ != null), "Invalid libraries for ScalaSource constructor.") - def this(url: URL, context: BundleContext) = this(url, Option(context) match { - case None => - throw new IllegalArgumentException("No BundleContext available to search for OSGi bundles.") - // TODO: Why not List()? - case Some(ctxt) => - val framework = ctxt.getProperty("karaf.framework") - val jar = new File( - ctxt.getProperty("karaf.base"), - ctxt.getProperty("karaf.framework." + framework)) - AbstractFile.getDirectory(jar) :: Bundles.create(ctxt.getBundles) - } - ) + def this(url: URL, context: BundleContext) = this (url, { + require(context != null, "No BundleContext available to search for OSGI bundles.") + val framework = context.getProperty("karaf.framework") + val jar = new File(context.getProperty("karaf.base"), context.getProperty("karaf.framework." + framework)) + AbstractFile.getDirectory(jar) :: Bundles.create(context.getBundles) + }) /**********************************************************************/ @@ -69,53 +63,28 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr a common interface using the "toByteArray" method is invalidated. In our specific case, this means that it useless to override the input(), toCharArray() or toByteArray() methods to intercept and rewrite on the - fly what is read from the file. + fly what is read from the file. Such a situation is not satisfactory. We therefore chose not to inherit from the PlainFile, but to prefer - composition over inheritance. Which the reason why we have a plainFile + composition over inheritance. Which is the reason why we have a plainFile field: fooling this pattern-matching. */ - val plainFile: PlainFile = new PlainFile(new File(url.toURI)) + private val plainFile: PlainFile = new PlainFile(new File(url.toURI)) override def name: String = plainFile.name - override def path: String = plainFile.path - override def absolute: AbstractFile = plainFile.absolute - override def container: AbstractFile = plainFile.container - override def file: File = plainFile.file - - override def create(): Unit = plainFile.create() - - override def delete(): Unit = plainFile.delete() - + override def create() {plainFile.create()} + override def delete() {plainFile.delete()} override def isDirectory: Boolean = plainFile.isDirectory - override def lastModified: Long = plainFile.lastModified - override def input: InputStream = plainFile.input - - override def toByteArray: Array[Byte] = - - /* NOTE: If the sizeOption is not properly overriden, the AbstractFile - default implementation of sizeOption will blow up. Hence the 'catch'. - - These composition vs. inheritance bugs are hard to find. In case this - happens, continue delegating calls to plainFile. */ - - try {super.toByteArray} catch {case e => e.printStackTrace(); throw e} - override def output: OutputStream = plainFile.output - - override def sizeOption = plainFile.sizeOption - override def iterator: Iterator[AbstractFile] = plainFile.iterator - override def lookupName(name: String, directory: Boolean): AbstractFile = plainFile.lookupName(name, directory) - override def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile = plainFile.lookupNameUnchecked(name, directory) @@ -123,23 +92,58 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr /* This call needs to be delegated to ensure that the referenced file is named properly. The implementation in PlainFile removes the file: URI prefix that is fed to a ScalaSource instance at construct-time. */ - plainFile.toString + plainFile.toString() + + /* The two following items need special care, since this is the IO interface + between ScalaSource files and the embedded compiler. + */ + + override def toByteArray: Array[Byte] = + /* NOTE: If the sizeOption is not properly overriden, the AbstractFile + default implementation of sizeOption will blow up. Hence the 'catch'. + + These composition vs. inheritance bugs are hard to find. In case this + happens, continue delegating calls to plainFile. */ + try super.toByteArray catch { + case e: java.util.NoSuchElementException => + val exc = new RuntimeException("Likely an implementation error: sizeOption in ScalaSource is not properly overriden.", e) + report(exc) + throw exc + } + + override def sizeOption = plainFile.sizeOption + /**********************************************************************/ + private var exception: Option[Exception] = None + + private def report(e: Exception) { + exception match { + case None => exception = Some(e) + case Some(_) => {} + } + } + def compile(): AbstractFile = { LOG.debug("Compiling " + this + " using embedded Scala compiler.") - try {(new ScalaCompiler(libraries)).compile(this)} - catch { + try { + exception = None + (new ScalaCompiler(libraries)).compile(this) + } catch { case e: ScalaCompileFailure => - // TODO: We here pass the same libs as the AbstractFile. Would - // be nicer to trim down to just what is the needed for the - // error-reporting bundle. But, oh well... - (new ScalaCompiler(libraries)).compile(new ScrewedSource(this)) + exception match { + case None => + // TODO: We here pass the same libs as the AbstractFile. Would + // be nicer to trim down to just what is the needed for the + // error-reporting bundle. But, oh well... + (new ScalaCompiler(libraries)).compile(new ScrewedSource(this)) + case Some(exc) => throw exc + } } } - def archive(dir: AbstractFile) = { + private def archive(dir: AbstractFile) = { LOG.debug("Archiving compiled " + this + " into an OSGi bundle.") (new ScalaArchiver(libraries)).archive(dir, this) } @@ -153,12 +157,9 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr def manifest() { val source = io.Source.fromInputStream(input).getLines().mkString("\n") - //LOG.info ("Manifest: \n" + source) import parser.ScriptParser._ - val c: ParseResult[List[parser.Item]] = parse(source) -// LOG.info("Comment:\n" + c) /* TODO: Extract manifest from this abstract file. */ } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala index 213b388..0854751 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaURLHandler.scala @@ -31,12 +31,12 @@ import org.osgi.framework.BundleContext * on the fly. Needs to be registered in the OSGi registry. */ class ScalaURLHandler extends AbstractURLStreamHandlerService { - + private val LOG: Log = LogFactory.getLog(classOf[ScalaURLHandler]) private val PREFIX: String = "scala:" private val SYNTAX: String = PREFIX + "" - @BeanProperty var bundleContext : BundleContext = null + @BeanProperty var bundleContext: BundleContext = null /** * Open the connection for the given URL. @@ -46,9 +46,8 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { * @throws IOException if an error occurs or if the URL is malformed. */ def openConnection(url: URL): URLConnection = { - if (url.getPath == null || url.getPath.trim.length == 0) { + if (url.getPath == null || url.getPath.trim.length == 0) throw new MalformedURLException("Path can not be null or empty. Syntax: " + SYNTAX) - } LOG.debug("Scala source URL is: [" + url.getPath + "]") new Connection(url) } @@ -57,23 +56,20 @@ class ScalaURLHandler extends AbstractURLStreamHandlerService { override def getInputStream: InputStream = { try { - val url = if (source.toExternalForm.startsWith(PREFIX)) { - new URL(source.toExternalForm.substring(PREFIX.length)) - } else { - source - } - - new ScalaSource (url, bundleContext).transform() + val url = + if (source.toExternalForm.startsWith(PREFIX)) + new URL(source.toExternalForm.substring(PREFIX.length)) + else source - } - catch { - case e: Exception => { + new ScalaSource(url, bundleContext).transform() + } catch { + case e: Exception => LOG.error("Error creating bundle from Scala source code", e) throw e - } } } - def connect () {} + def connect() {} } + } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala index fec1626..a6e4bb8 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScrewedSource.scala @@ -20,33 +20,30 @@ import java.io._ import org.apache.commons.logging.LogFactory import tools.nsc.io.AbstractFile -class ScrewedSource (var f : AbstractFile) extends AbstractFile { +class ScrewedSource(var f: AbstractFile) extends AbstractFile { - final val LOG = LogFactory.getLog(classOf[ScrewedSource]) + final val LOG = LogFactory.getLog(classOf[ScrewedSource]) - LOG.debug ("ScrewedSource for " + f.path) + LOG.debug("ScrewedSource for " + f.path) - def fail(msg : String) : Nothing = { - val s = "ScrewedSource: " + msg + " unimplemented." + def fail(msg: String): Nothing = { + val s = "ScrewedSource: " + msg + " unimplemented." LOG.debug(s) throw new Exception(s) - } + } - override def lookupNameUnchecked (name : String, directory : Boolean) = fail("lookupNameUnchecked") - - override def lookupName (name : String, directory : Boolean) = fail("lookupName") - - override def iterator = fail("iterator") - - override def output = fail("output") + override def lookupNameUnchecked(name: String, directory: Boolean) = fail("lookupNameUnchecked") + override def lookupName(name: String, directory: Boolean) = fail("lookupName") + override def iterator = fail("iterator") + override def output = fail("output") /* sizeOption needs to be overriden to provide the length of the input stream. It is NOT declared abstract in AbstractFile, which leads to weird IO errors if this override is not properly made. */ - override def sizeOption = Some(code.length) + override def sizeOption = Some(code.length) - def code = """ + def code = """ import org.osgi.framework.{BundleContext, BundleActivator} @@ -62,27 +59,20 @@ class ScrewedSource (var f : AbstractFile) extends AbstractFile { } - """.getBytes("UTF-8") // TODO: Check if global.settings.encoding.value is not better. - // see line 77 of AbstractFile.scala in the compiler's source code. - - override def input = new ByteArrayInputStream(code) - - override def lastModified = fail("lastModified") - - override def isDirectory = fail("isDirectory") - - override def delete() { fail("delete")} - - override def create() { fail("create")} - - override def file = fail("file") - - override def container = fail("container") - - override def absolute = fail("absolute") - - override def path = f.path - - override def name = f.name + """.getBytes("UTF-8") + // TODO: Check if global.settings.encoding.value is not better. + // see line 77 of AbstractFile.scala in the compiler's source code. + + override def input = new ByteArrayInputStream(code) + override def lastModified = fail("lastModified") + override def isDirectory = fail("isDirectory") + override def delete() {fail("delete")} + override def create() {fail("create")} + override def file = fail("file") + override def container = fail("container") + override def absolute = fail("absolute") + + override def path = f.path + override def name = f.name } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index f5bc698..51444f0 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -78,17 +78,8 @@ class ScalaArchiver(bundles: List[AbstractFile]) { def entries(dir: AbstractFile, path: String)(action: (String, AbstractFile) => Unit): Unit = { dir.foreach { (file: AbstractFile) => - println("Iterating through compiled files: " + file) - val name = if (path.length == 0) {file.name} - else {path + "/" + file.name} - if (file.isDirectory) { - println(" File is a directory.") - entries(file, name)(action) - } - else { - println(" File is not a directory.") - action(name, file) - } + val name = if (path.length == 0) file.name else path + "/" + file.name + if (file.isDirectory) entries(file, name)(action) else action(name, file) } } @@ -122,32 +113,26 @@ class ScalaArchiver(bundles: List[AbstractFile]) { override protected def trace = true override def findClass(name: String): Class[_] = try { - println("We are trying to find the class " + name) // let's try the bundle we're generating first super.findClass(name) } catch { case e: ClassNotFoundException => - println("The class " + name + " could not be found.") // and then fall back to the rest of the bundles findClassInBundles(name) } def findClassInBundles(name: String): Class[_] = classloaders.map(cl => findClass(name, cl)).find(cls => cls.isDefined) match { - case Some(cls) => println("FOUND!!!!!"); cls.get - case None => println("NOT FOUND!!!!"); throw new ClassNotFoundException(name) + case Some(cls) => cls.get + case None => throw new ClassNotFoundException(name) } def findClass(name: String, loader: AbstractFileClassLoader) = - try { - println("Trying to find " + name + " in some custom bundle.") - Some(loader.findClass(name)) - } catch { + try Some(loader.findClass(name)) catch { case e: /* ClassNotFoundException */ Exception => /* TODO: Original code was catching the ClassNotFoundException, - and an inadequate exception was falling through. So I widened - the range of caught exceptions, but this is only a workaround. */ - println("But wasn't found...") + and an inadequate exception was falling through. So I widened + the range of caught exceptions, but this is only a workaround. */ None } } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index d5fb39c..ece5ecb 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -42,21 +42,12 @@ object Bundles { lazy val (path: String, name: String) = getPathAndName(url) lazy val fullName: String = (path :: name :: Nil).filter(!_.isEmpty).mkString("/") - /** - * @return null - */ def file: File = null - /** - * @return last modification time or 0 if not known - */ - def lastModified: Long = - try {url.openConnection.getLastModified} - catch {case _ => 0} + def lastModified: Long = try url.openConnection.getLastModified catch {case _ => 0} @throws(classOf[IOException]) - def container: AbstractFile = Option(parent).getOrElse( - throw new IOException("No container")) + def container: AbstractFile = Option(parent).getOrElse(throw new IOException("No container")) @throws(classOf[IOException]) def input: InputStream = url.openStream() @@ -86,44 +77,30 @@ object Bundles { class DirEntry(val bundle: Bundle, bundleUrl: URL, parent: DirEntry) extends BundleEntry(bundleUrl, parent) { - /** - * @return true - */ def isDirectory: Boolean = true override def elements: Iterator[AbstractFile] = { @tailrec def removeTrailingSlash(s: String): String = - if (s == null || s.length == 0) { - s - } - else if (s.last == '/') { - removeTrailingSlash(s.substring(0, s.length - 1)) - } - else { - s - } + if (s == null || s.length == 0) s + else if (s.last == '/') removeTrailingSlash(s.substring(0, s.length - 1)) + else s import scala.collection.JavaConverters._ bundle.getEntryPaths(fullName).asScala.map { - case entry: String => { + case entry: String => val entryUrl = Option(Option(bundle.getResource("/" + entry)). - // Bundle.getReource seems to be inconsistent with respect to requiring - // a trailing slash. - getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) + // Bundle.getReource seems to be inconsistent with respect to requiring + // a trailing slash. + getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) entryUrl match { case None => throw new IllegalStateException("For some reason, OSGi will not let use the entry " + entry) case Some(url) => - if (entry.endsWith(".class")) { - new FileEntry(bundle, url, DirEntry.this) - } - else { - new DirEntry(bundle, url, DirEntry.this) - } + if (entry.endsWith(".class")) new FileEntry(bundle, url, DirEntry.this) + else new DirEntry(bundle, url, DirEntry.this) } - } case _ => throw new ClassCastException("Items other than Strings found in an OSGi bundle's entry paths.") } @@ -155,9 +132,6 @@ object Bundles { class FileEntry(val bundle: Bundle, url: URL, parent: DirEntry) extends BundleEntry(url, parent) { - /** - * @return false - */ def isDirectory: Boolean = false override def sizeOption: Option[Int] = Some(bundle.getEntry(fullName).openConnection().getContentLength) @@ -174,13 +148,9 @@ object Bundles { def absolute = unsupported("absolute() is unsupported") - def create() { - unsupported("create() is unsupported") - } + def create() {unsupported("create() is unsupported")} - def delete() { - unsupported("create() is unsupported") - } + def delete() {unsupported("create() is unsupported")} } /** @@ -191,26 +161,17 @@ object Bundles { var result: List[AbstractFile] = List() for (bundle <- bundles; val index = bundles.indexOf(bundle)) { var url = bundle.getResource("/") - if (url == null) { - url = bundle.getResource("") - } + if (url == null) url = bundle.getResource("") if (url != null) { if ("file" == url.getProtocol) { - try { - result = new PlainFile(new File(url.toURI)) :: result - } catch { - case e: URISyntaxException => - throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) + try result = new PlainFile(new File(url.toURI)) :: result + catch {case e: URISyntaxException => + throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) } - } - else { - result = Bundles.create(bundle) :: result - } - } - else { - LOG.warn("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName); + } else result = Bundles.create(bundle) :: result } + else LOG.warn("Cannot retreive resources from Bundle. Skipping " + bundle.getSymbolicName); } result } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 735e603..158b1f1 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -82,23 +82,12 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val reporter = new StoreReporter { - override def info0 (pos: Position, msg: String, severity: Severity, force: Boolean) { - LOG.warn(pos + ":" + msg) - super.info0(pos, msg: String, severity, force) - } - - } - -/* lazy val reporter = new AbstractReporter { - - def displayPrompt () { println("compiler:") } - - def display(position: Position, msg: String, severity: Severity) { - LOG.warn(position + ":" + msg) + override def info0(pos: Position, msg: String, severity: Severity, force: Boolean) { + LOG.warn(pos + ":" + msg) + super.info0(pos, msg: String, severity, force) } - val settings = ScalaCompiler.this.settings - }*/ + } lazy val compiler = new Global(settings, reporter) { diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/VirtualDirectory.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/VirtualDirectory.scala deleted file mode 100644 index 1e0c6cd..0000000 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/VirtualDirectory.scala +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) FuseSource, Inc. - * http://fusesource.com - * - * Licensed 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.collection.{mutable=>mut} -import scala.tools.nsc.io.{VirtualFile, AbstractFile} - -package org.fusesource.slang.scala.deployer.compiler { - - -/** - * Temporary workaround for a bug in scala.tools.nsc.io.VirtualDirecotry - * This file can be removed as soon as Scala 2.8.0 is out - * - * NSC -- new Scala compiler - * Copyright 2005-2009 LAMP/EPFL - -class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory]) extends AbstractFile { - - def path: String = - maybeContainer match { - case None => name - case Some(parent) => parent.path+'/'+ name - } - def container = maybeContainer.get - def isDirectory = true - var lastModified: Long = System.currentTimeMillis - private def updateLastModified { - lastModified = System.currentTimeMillis - } - override def file = null - override def input = error("directories cannot be read") - override def output = error("directories cannot be written") - - private val files = mut.Map.empty[String, AbstractFile] - - // the toList is so that the directory may continue to be - // modified while its elements are iterated - def elements = files.values.toList.elements - - override def lookupName(name: String, directory: Boolean): AbstractFile = { - files.get(name) match { - case None => null - case Some(file) => - if (file.isDirectory == directory) - file - else - null - } - } - - override def fileNamed(name: String): AbstractFile = { - val existing = lookupName(name, false) - if (existing == null) { - val newFile = new VirtualFile(name, path+'/'+name) - files(name) = newFile - newFile - } else { - existing - } - } - - override def subdirectoryNamed(name: String): AbstractFile = { - val existing = lookupName(name, true) - if (existing == null) { - val dir = new VirtualDirectory(name, Some(this)) - files(name) = dir - dir - } else { - existing - } - } -} -*/ - -} diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala index a47663d..3b149b0 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/parser/ScriptParser.scala @@ -19,56 +19,57 @@ package org.fusesource.slang.scala.deployer.parser import scala.util.parsing.combinator._ sealed abstract class Item -case class Code (code : String) extends Item +case class Code(code: String) extends Item abstract class Commented extends Item -case class Comment (code : String) extends Commented -case class Manifest () extends Commented +case class Comment(code: String) extends Commented +case class Manifest() extends Commented object ManifestParser extends RegexParsers { - override def skipWhitespace = false + override def skipWhitespace = false - private def spaces = regex("""([ \t\n]|\n[ \t]*\*[ \t]*)*""".r) + private def spaces = regex("""([ \t\n]|\n[ \t]*\*[ \t]*)*""".r) - private def manifestHeader = spaces ~> regex("""OSGI-MANIFEST:""".r) <~ spaces ^^ { case _ : String => {}} + private def manifestHeader = spaces ~> regex("""OSGI-MANIFEST:""".r) <~ spaces ^^ {case _: String => {}} - private def manifest = regex("""\**""".r) ~> manifestHeader + private def manifest = regex("""\**""".r) ~> manifestHeader - def parse (comment : Comment) : Boolean = comment match { - case Comment (c) => parse (manifest, c) match { - case Success ((), _) => true - case Failure (msg, _) => false - case Error (msg, _) => throw new Exception ( - "Slang deployer parsing error: " + msg) - }} + def parse(comment: Comment): Boolean = comment match { + case Comment(c) => parse(manifest, c) match { + case Success((), _) => true + case Failure(msg, _) => false + case Error(msg, _) => throw new Exception("Slang deployer parsing error: " + msg) + } + } } object ScriptParser extends RegexParsers { - override def skipWhitespace = false + override def skipWhitespace = false - private def spaces = regex("""[ \t\n]*""".r) + private def spaces = regex("""[ \t\n]*""".r) - private def openComment = spaces ~> regex("""/\*""".r) + private def openComment = spaces ~> regex("""/\*""".r) - private def closeComment = regex("""\*/""".r) <~ spaces + private def closeComment = regex("""\*/""".r) <~ spaces - private def textComment = regex("""^((?!\*/).|\n)*""".r) ^^ (Comment(_)) + private def textComment = regex("""^((?!\*/).|\n)*""".r) ^^ (Comment(_)) - private def comment : Parser[Commented] = openComment ~> textComment <~ closeComment ^^ { - case c : Comment => ManifestParser.parse(c) match { - case true => Manifest () - case false => c - }} + private def comment: Parser[Commented] = openComment ~> textComment <~ closeComment ^^ { + case c: Comment => ManifestParser.parse(c) match { + case true => Manifest() + case false => c + } + } - /* NOTE: Use + instead of * in the following regexp - to avoid infinite loops while parsing. */ - private def code : Parser[Code] = regex("""^((?!/\*).|\n)+""".r) ^^ (Code(_)) + /* NOTE: Use + instead of * in the following regexp + to avoid infinite loops while parsing. */ + private def code: Parser[Code] = regex("""^((?!/\*).|\n)+""".r) ^^ (Code(_)) - private def items : Parser[List[Item]] = (( comment | code ) * ) + private def items: Parser[List[Item]] = ((comment | code) *) - def parse (s : String) : ParseResult[List[Item]] = parse (items, s) + def parse(s: String): ParseResult[List[Item]] = parse(items, s) } diff --git a/scala/deployer/src/test/resources/TestWithActivator.scala b/scala/deployer/src/test/resources/TestWithActivator.scala index a591f53..69ac6e1 100644 --- a/scala/deployer/src/test/resources/TestWithActivator.scala +++ b/scala/deployer/src/test/resources/TestWithActivator.scala @@ -29,4 +29,4 @@ class TestWithActivator extends BundleActivator { } } -} \ No newline at end of file +} From 11d24832b05e4529e063bc923620e5f1c90b5ee1 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 15:56:33 +0200 Subject: [PATCH 21/29] Silencing tracing of AbstractFileClassLoader. --- .../org/fusesource/slang/scala/deployer/ScalaSource.scala | 3 ++- .../slang/scala/deployer/archiver/ScalaArchiver.scala | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 7a5260e..6867ded 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -106,7 +106,8 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr happens, continue delegating calls to plainFile. */ try super.toByteArray catch { case e: java.util.NoSuchElementException => - val exc = new RuntimeException("Likely an implementation error: sizeOption in ScalaSource is not properly overriden.", e) + val exc = new RuntimeException( + "Likely an implementation error: sizeOption in ScalaSource is not properly overriden.", e) report(exc) throw exc } diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index 51444f0..6c225b6 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -110,7 +110,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, getClass.getClassLoader) { // Set to true to trace classloader activity. - override protected def trace = true + //override protected def trace = true override def findClass(name: String): Class[_] = try { // let's try the bundle we're generating first From afc3a4ab3de8bc9b2a26ce43fc2c1f1d13e46c07 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 16:09:42 +0200 Subject: [PATCH 22/29] Fixing logging statements and other stack traces. --- .../slang/scala/deployer/archiver/ScalaArchiver.scala | 4 +--- .../slang/scala/deployer/compiler/ScalaCompiler.scala | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index 6c225b6..ecb54c7 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -61,9 +61,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { LOG.debug("Discovered bundle activator " + theType.getName) props.put("Bundle-Activator", theType.getName) } - } catch { - case e: Exception => e.printStackTrace() - } + } // catch {case e: Exception => e.printStackTrace()} } jar.close() diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 158b1f1..6df6592 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -61,7 +61,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { stack trace to stdout. */ val run = try { new compiler.Run } catch {case e : Throwable => LOG.debug ("Failed to instantiate internal compiler.Run framework: " + e.getMessage) - e.printStackTrace() + //e.printStackTrace() throw e } @@ -83,7 +83,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { lazy val reporter = new StoreReporter { override def info0(pos: Position, msg: String, severity: Severity, force: Boolean) { - LOG.warn(pos + ":" + msg) + LOG.debug(pos + ":" + msg) super.info0(pos, msg: String, severity, force) } From 5f9cb74124ace1d8d48c5c6446b0e61b13774ced Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 16:12:37 +0200 Subject: [PATCH 23/29] Fixing logging levels. --- .../slang/scala/deployer/compiler/ScalaCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 6df6592..0a6649f 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -36,7 +36,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { final val LOG = LogFactory.getLog(classOf[ScalaCompiler]) def compile(source: AbstractFile) : AbstractFile = { - LOG.info("Compiling " + source) + LOG.debug("Compiling " + source) val dir = new VirtualDirectory("memory", None) settings.outputDirs.setSingleOutput(dir) From 349808d96b9a554a253228fd1b8268b9b9cd4eee Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 16:15:27 +0200 Subject: [PATCH 24/29] Fixing compiler verbosity. --- .../slang/scala/deployer/compiler/ScalaCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala index 0a6649f..35ab65b 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/ScalaCompiler.scala @@ -40,7 +40,7 @@ class ScalaCompiler(bundles: List[AbstractFile]) { val dir = new VirtualDirectory("memory", None) settings.outputDirs.setSingleOutput(dir) - settings.verbose.value = true + settings.verbose.value = false settings.debug.value = false /* Set to true for logging debugging info. */ settings.Ylogcp.value = false /* Set to true for classpath informations. */ /* Yno-predefs and Yno-imports may be useful */ From d92f5e6351cfa55348f51e7f6a5232eda9d403c9 Mon Sep 17 00:00:00 2001 From: Carlo Jelmini Date: Tue, 27 Mar 2012 16:36:46 +0200 Subject: [PATCH 25/29] Review --- .../scala/deployer/archiver/ScalaArchiver.scala | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala index ecb54c7..f042335 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/archiver/ScalaArchiver.scala @@ -36,11 +36,11 @@ import org.fusesource.slang.scala.deployer.ScalaSource */ class ScalaArchiver(bundles: List[AbstractFile]) { - val LOG = LogFactory.getLog(classOf[ScalaArchiver]) + private val LOG = LogFactory.getLog(classOf[ScalaArchiver]) // classloaders contains a classloader supposed to be able to load classes // from a given bundles. In fact, one classloader for each bundle. - val classloaders = bundles.map(new AbstractFileClassLoader(_, getClass.getClassLoader)) + private val classloaders = bundles.map(new AbstractFileClassLoader(_, getClass.getClassLoader)) def archive(dir: AbstractFile, source: ScalaSource): InputStream = { @@ -70,18 +70,19 @@ class ScalaArchiver(bundles: List[AbstractFile]) { createBundle(new ByteArrayInputStream(bytes.toByteArray), props, bsn(source.url)) } - def entries(dir: AbstractFile)(action: (String, AbstractFile) => Unit): Unit = + private def entries(dir: AbstractFile)(action: (String, AbstractFile) => Unit) { entries(dir, "")(action) + } - def entries(dir: AbstractFile, path: String)(action: (String, AbstractFile) => Unit): Unit = { + private def entries(dir: AbstractFile, path: String)(action: (String, AbstractFile) => Unit) { dir.foreach { (file: AbstractFile) => val name = if (path.length == 0) file.name else path + "/" + file.name - if (file.isDirectory) entries(file, name)(action) else action(name, file) + if (file.isDirectory) entries(file, name) { action } else action(name, file) } } - def archiveFile(file: AbstractFile, jar: JarOutputStream, name: String) = { + private def archiveFile(file: AbstractFile, jar: JarOutputStream, name: String) = { val entry = new JarEntry(name) jar.putNextEntry(entry) val bytes = new Array[Byte](1024) @@ -94,7 +95,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { jar.closeEntry() } - def bsn(url: URL) = { + private def bsn(url: URL) = { var result = url.getPath if (result.endsWith(".scala")) { result = result.substring(0, result.length - 6) @@ -105,7 +106,7 @@ class ScalaArchiver(bundles: List[AbstractFile]) { result.replaceAll("/", ".") } - def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, getClass.getClassLoader) { + private def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, getClass.getClassLoader) { // Set to true to trace classloader activity. //override protected def trace = true From 9158174de95f56b6eab323ddaedd994b23297f1b Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 17:35:02 +0200 Subject: [PATCH 26/29] Removing manifest parsing, as it is not robust enough yet. --- .../scala/org/fusesource/slang/scala/deployer/ScalaSource.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 6867ded..89f9aef 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -151,7 +151,7 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr def transform() = { LOG.info("Transforming " + this + " into an OSGi bundle.") - manifest() + //manifest() // TODO: Not robust yet archive(compile()) } From c52a425cfaa8b5a7f61ce045cf3c2f1168c23ab2 Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Tue, 27 Mar 2012 17:42:07 +0200 Subject: [PATCH 27/29] Able to print stack trace of parser combinators in infinite loop now. --- .../scala/org/fusesource/slang/scala/deployer/ScalaSource.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala index 89f9aef..d0a5dde 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/ScalaSource.scala @@ -151,7 +151,7 @@ class ScalaSource(val url: URL, val libraries: List[AbstractFile]) extends Abstr def transform() = { LOG.info("Transforming " + this + " into an OSGi bundle.") - //manifest() // TODO: Not robust yet + // try { manifest() } catch {case e : Throwable => e.printStackTrace(); throw e} // TODO: Not robust enough yet. archive(compile()) } From bfc33d155980a48972f2e96956dd3def203775d0 Mon Sep 17 00:00:00 2001 From: "nicolas.jorand" Date: Wed, 11 Apr 2012 17:10:39 +0200 Subject: [PATCH 28/29] Nicolas' change to Slang code for XTech codebase: Correct error when getting ressource from bundle deployed as a xml file Change the version to have a XTech customized Add scm information and no push changed after release [maven-release-plugin] prepare release slang-1.0.0.xtech-01 [maven-release-plugin] prepare for next development iteration [maven-release-plugin] rollback the release of slang-1.0.0.xtech-01 Add distribution management Change the project name to have an explicit tag created by maven [maven-release-plugin] prepare release slang-1.0.0.xtech-01 [maven-release-plugin] rollback the release of slang-1.0.0.xtech-01 commit automatically on release [maven-release-plugin] prepare release slang-1.0.0.xtech-01 Nicolas' changes - rebased on github version. --- .gitignore | 1 + features/pom.xml | 218 +++++++------ pom.xml | 305 ++++++++++-------- scala/common/pom.xml | 114 ++++--- scala/deployer/pom.xml | 213 ++++++------ .../scala/deployer/compiler/Bundles.scala | 31 +- scala/itests/pom.xml | 94 +++--- scala/pom.xml | 201 ++++++------ 8 files changed, 607 insertions(+), 570 deletions(-) diff --git a/.gitignore b/.gitignore index 50ecf13..2f54d56 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ webgen.cache *.i?? .idea *.swp +atlassian-ide-plugin.xml diff --git a/features/pom.xml b/features/pom.xml index ffb719e..bee661f 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -1,122 +1,120 @@ - + - + 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. + --> - - parent - org.fusesource.slang - 1.0.0-SNAPSHOT - - - 4.0.0 + + parent + org.fusesource.slang + 1.0.0-SNAPSHOT + - features - Slang :: Features + 4.0.0 - - - org.osgi - org.osgi.core - provided - - - org.apache.aries.blueprint - org.apache.aries.blueprint - provided - - - org.ops4j.pax.logging - pax-logging-api - provided - - - org.apache.felix - org.apache.felix.fileinstall - provided - - + features + Slang :: Features - - - - ${pom.basedir}/src/main/resources - true - - **/* - - - - - - org.apache.karaf.tooling - features-maven-plugin - ${karaf.version} - - - validate - process-resources - - validate - - - target/classes/features.xml - - - - - - - org.slf4j - slf4j-simple - 1.6.1 - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.7 - - - attach-artifacts - package - - attach-artifact - - - - - target/classes/features.xml - xml - features - - - - - - - - + + + org.osgi + org.osgi.core + provided + + + org.apache.aries.blueprint + org.apache.aries.blueprint + provided + + + org.ops4j.pax.logging + pax-logging-api + provided + + + org.apache.felix + org.apache.felix.fileinstall + provided + + + + + + + ${pom.basedir}/src/main/resources + true + + **/* + + + + + + org.apache.karaf.tooling + features-maven-plugin + ${karaf.version} + + + validate + process-resources + + validate + + + target/classes/features.xml + + + + + + + org.slf4j + slf4j-simple + 1.6.1 + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + attach-artifacts + package + + attach-artifact + + + + + target/classes/features.xml + xml + features + + + + + + + + diff --git a/pom.xml b/pom.xml index 2fd182b..55f88c1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,142 +1,173 @@ - - - 4.0.0 - - org.fusesource.slang - parent - pom - 1.0.0-SNAPSHOT - Slang - 2010 - - - 0.3.1 - [$(version;==;$(@)),$(version;+;$(@))) - 3.1.10 - 1.4.0 - 2.3.6 - 4.8.1 - 2.2.5 - 4.2.0 - 1.2.0 - 1.6.3 - 1.2.0 - 2.9.1 - - UTF-8 - - - - scala - features - - - - install - - - org.apache.felix - maven-bundle-plugin - ${felix.plugin.version} - true - - - org.apache.maven.plugins - maven-resources-plugin - 2.5 - - - - - - - - org.apache.felix - org.osgi.core - ${felix.osgi.version} - provided - - - org.ops4j.pax.logging - pax-logging-api - ${pax.logging.version} - provided - - - org.apache.felix - org.apache.felix.fileinstall - ${felix.fileinstall.version} - provided - - - org.ops4j.pax.swissbox - pax-swissbox-bnd - 1.2.0 - - - org.osgi - org.osgi.core - ${osgi.version} - - - org.apache.aries.blueprint - org.apache.aries.blueprint - ${aries.blueprint.version} - - - org.apache.felix - javax.servlet - - - - - - - junit - junit - ${junit.version} - test - - - org.ops4j.pax.exam - pax-exam - ${pax.exam.version} - test - - - org.ops4j.pax.exam - pax-exam-container-default - ${pax.exam.version} - test - - - org.ops4j.pax.exam - pax-exam-junit - ${pax.exam.version} - test - - - + + + 4.0.0 + + org.fusesource.slang + parent + pom + 1.0.0.SNAPSHOT + Slang + 2010 + + + 0.3.1 + [$(version;==;$(@)),$(version;+;$(@))) + 3.1.10 + 1.4.0 + 2.3.6 + 4.8.1 + 2.2.5 + 4.2.0 + 1.2.0 + 1.6.3 + 1.2.0 + 2.9.1 + + UTF-8 + + + + scala + features + + + + scm:git:git@wiki.crossing-tech.com:slang.git + scm:git:git@wiki.crossing-tech.com:slang.git + + + + install + + + org.apache.felix + maven-bundle-plugin + ${felix.plugin.version} + true + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + + + + maven-release-plugin + 2.2.2 + + true + + + + + + + + + + org.apache.felix + org.osgi.core + ${felix.osgi.version} + provided + + + org.ops4j.pax.logging + pax-logging-api + ${pax.logging.version} + provided + + + org.apache.felix + org.apache.felix.fileinstall + ${felix.fileinstall.version} + provided + + + org.ops4j.pax.swissbox + pax-swissbox-bnd + 1.2.0 + + + org.osgi + org.osgi.core + ${osgi.version} + + + org.apache.aries.blueprint + org.apache.aries.blueprint + ${aries.blueprint.version} + + + org.apache.felix + javax.servlet + + + + + + + junit + junit + ${junit.version} + test + + + org.ops4j.pax.exam + pax-exam + ${pax.exam.version} + test + + + org.ops4j.pax.exam + pax-exam-container-default + ${pax.exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit + ${pax.exam.version} + test + + + + + + + + nexusXtech + Nexus + https://wiki.crossing-tech.com/nexus/content/repositories/releases + + + + nexusXtech + Nexus + https://wiki.crossing-tech.com/nexus/content/repositories/snapshots + + diff --git a/scala/common/pom.xml b/scala/common/pom.xml index 87f8bcb..e617b62 100644 --- a/scala/common/pom.xml +++ b/scala/common/pom.xml @@ -1,69 +1,67 @@ - + - + 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. + --> - - scala - org.fusesource.slang - 1.0.0-SNAPSHOT - + + scala + org.fusesource.slang + 1.0.0-SNAPSHOT + - 4.0.0 + 4.0.0 - org.fusesource.slang.scala - org.fusesource.slang.scala.common - bundle - - Slang :: Scala :: Common + org.fusesource.slang.scala + org.fusesource.slang.scala.common + bundle - - - - org.apache.felix - org.osgi.core - - + Slang :: Scala :: Common - - - - org.apache.felix - maven-bundle-plugin - - - ${project.artifactId} - ${project.artifactId}*;version=${project.version} - - !${project.artifactId}*, - * - - <_versionpolicy>${bnd.version.policy} - - - - - - + + + + org.apache.felix + org.osgi.core + + - \ No newline at end of file + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + ${project.artifactId}*;version=${project.version} + + !${project.artifactId}*, + * + + <_versionpolicy>${bnd.version.policy} + + + + + + + + diff --git a/scala/deployer/pom.xml b/scala/deployer/pom.xml index f038416..6dec21f 100644 --- a/scala/deployer/pom.xml +++ b/scala/deployer/pom.xml @@ -1,120 +1,119 @@ - + - + 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. + --> - 4.0.0 + 4.0.0 - - scala - org.fusesource.slang - 1.0.0-SNAPSHOT - + + scala + org.fusesource.slang + 1.0.0-SNAPSHOT + - org.fusesource.slang.scala - org.fusesource.slang.scala.deployer - bundle + org.fusesource.slang.scala + org.fusesource.slang.scala.deployer + bundle - Slang :: Scala :: Deployer + Slang :: Scala :: Deployer - - - org.apache.felix - org.osgi.core - provided - - - org.scala-lang - scala-library - - - org.ops4j.pax.logging - pax-logging-api - - - org.apache.felix - org.apache.felix.fileinstall - - - org.ops4j.pax.swissbox - pax-swissbox-bnd - true - - - junit - junit - - + + + org.apache.felix + org.osgi.core + provided + + + org.scala-lang + scala-library + + + org.ops4j.pax.logging + pax-logging-api + + + org.apache.felix + org.apache.felix.fileinstall + + + org.ops4j.pax.swissbox + pax-swissbox-bnd + true + + + junit + junit + + - - - - org.apache.maven.plugins - maven-eclipse-plugin - 2.9 - - true - - ch.epfl.lamp.sdt.core.scalabuilder - - - ch.epfl.lamp.sdt.core.scalanature - - - org.eclipse.jdt.launching.JRE_CONTAINER - ch.epfl.lamp.sdt.launching.SCALA_CONTAINER - - - - - org.apache.felix - maven-bundle-plugin - - - - ${project.artifactId};blueprint.graceperiod:=false - ${project.artifactId}*;version=${project.version} - - !${project.artifactId}*, - org.apache.commons.logging;version="[1.1, 1.2)", - * - - <_versionpolicy>${bnd.version.policy} - pax-swissbox-bnd,bndlib,ops4j-base-lang - true - - - - - + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.9 + + true + + ch.epfl.lamp.sdt.core.scalabuilder + + + ch.epfl.lamp.sdt.core.scalanature + + + org.eclipse.jdt.launching.JRE_CONTAINER + ch.epfl.lamp.sdt.launching.SCALA_CONTAINER + + + + + org.apache.felix + maven-bundle-plugin + + + + ${project.artifactId};blueprint.graceperiod:=false + ${project.artifactId}*;version=${project.version} + + !${project.artifactId}*, + org.apache.commons.logging;version="[1.1, 1.2)", + * + + <_versionpolicy>${bnd.version.policy} + pax-swissbox-bnd,bndlib,ops4j-base-lang + true + + + + + + + + + + org.scala-tools + maven-scala-plugin + 2.15.2 + + + - - - - org.scala-tools - maven-scala-plugin - 2.15.2 - - - - diff --git a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala index ece5ecb..356116c 100644 --- a/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala +++ b/scala/deployer/src/main/scala/org/fusesource/slang/scala/deployer/compiler/Bundles.scala @@ -44,7 +44,9 @@ object Bundles { def file: File = null - def lastModified: Long = try url.openConnection.getLastModified catch {case _ => 0} + def lastModified: Long = try url.openConnection.getLastModified catch { + case _ => 0 + } @throws(classOf[IOException]) def container: AbstractFile = Option(parent).getOrElse(throw new IOException("No container")) @@ -93,10 +95,12 @@ object Bundles { val entryUrl = Option(Option(bundle.getResource("/" + entry)). // Bundle.getReource seems to be inconsistent with respect to requiring // a trailing slash. - getOrElse(bundle.getResource("/" + removeTrailingSlash(entry)))) + getOrElse(Option(bundle.getResource("/" + removeTrailingSlash(entry))). + // If the bundle is a xml file like activemq.xml, the entry META-INF cannot be reached so return the root URL + getOrElse(bundle.getResource("/")))) entryUrl match { case None => - throw new IllegalStateException("For some reason, OSGi will not let use the entry " + entry) + throw new IllegalStateException("For some reason, OSGi will not let use the entry " + entry + " of bundleID " + bundle.getBundleId) case Some(url) => if (entry.endsWith(".class")) new FileEntry(bundle, url, DirEntry.this) else new DirEntry(bundle, url, DirEntry.this) @@ -125,9 +129,13 @@ object Bundles { def absolute = unsupported("absolute() is unsupported") - def create() {unsupported("create() is unsupported")} + def create() { + unsupported("create() is unsupported") + } - def delete() {unsupported("create() is unsupported")} + def delete() { + unsupported("create() is unsupported") + } } class FileEntry(val bundle: Bundle, url: URL, parent: DirEntry) extends BundleEntry(url, parent) { @@ -148,9 +156,13 @@ object Bundles { def absolute = unsupported("absolute() is unsupported") - def create() {unsupported("create() is unsupported")} + def create() { + unsupported("create() is unsupported") + } - def delete() {unsupported("create() is unsupported")} + def delete() { + unsupported("create() is unsupported") + } } /** @@ -166,8 +178,9 @@ object Bundles { if (url != null) { if ("file" == url.getProtocol) { try result = new PlainFile(new File(url.toURI)) :: result - catch {case e: URISyntaxException => - throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) + catch { + case e: URISyntaxException => + throw new IllegalArgumentException("Can't determine url of bundle " + bundle, e) } } else result = Bundles.create(bundle) :: result } diff --git a/scala/itests/pom.xml b/scala/itests/pom.xml index ab9530e..4606087 100644 --- a/scala/itests/pom.xml +++ b/scala/itests/pom.xml @@ -1,49 +1,47 @@ - - - - - - scala - org.fusesource.slang - 1.0.0-SNAPSHOT - - 4.0.0 - - org.fusesource.slang.scala - org.fusesource.scaraf.itests - Slang :: Scala :: Integration tests - - - - org.ops4j.pax.exam - pax-exam - - - org.ops4j.pax.exam - pax-exam-container-default - - - org.ops4j.pax.exam - pax-exam-junit - - - - \ No newline at end of file + + + + + + scala + org.fusesource.slang + 1.0.0-SNAPSHOT + + 4.0.0 + + org.fusesource.slang.scala + org.fusesource.scaraf.itests + Slang :: Scala :: Integration tests + + + + org.ops4j.pax.exam + pax-exam + + + org.ops4j.pax.exam + pax-exam-container-default + + + org.ops4j.pax.exam + pax-exam-junit + + + + diff --git a/scala/pom.xml b/scala/pom.xml index 65a6c46..490f3fe 100644 --- a/scala/pom.xml +++ b/scala/pom.xml @@ -1,116 +1,115 @@ - + 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. + --> - 4.0.0 + 4.0.0 - - parent - org.fusesource.slang - 1.0.0-SNAPSHOT - + + parent + org.fusesource.slang + 1.0.0-SNAPSHOT + - scala - pom - 1.0.0-SNAPSHOT - Slang :: Scala + scala + pom + Slang :: Scala - - deployer - itests - common - + + deployer + itests + common + - - - scala-tools.org - Scala-Tools Maven2 Repository - http://scala-tools.org/repo-releases - - false - - - + + + scala-tools.org + Scala-Tools Maven2 Repository + http://scala-tools.org/repo-releases + + false + + + - - - org.scala-lang - scala-compiler - - - - - - scala-tools.org - Scala-Tools Maven2 Repository - http://scala-tools.org/repo-releases - - false - - - - - - install - src/main/scala - src/test/scala - - - org.scala-tools - maven-scala-plugin - 2.15.2 - - - - compile - testCompile - - - - - - org.apache.felix - maven-bundle-plugin - ${felix.plugin.version} - true - - - - - - - org.scala-lang - scala-library - ${scala.version} - - - org.scala-lang - scala-compiler - ${scala.version} - - - org.scalamodules - scalamodules.core - ${scalamodules.version} - + + org.scala-lang + scala-compiler + - - \ No newline at end of file + + + scala-tools.org + Scala-Tools Maven2 Repository + http://scala-tools.org/repo-releases + + false + + + + + + install + src/main/scala + src/test/scala + + + org.scala-tools + maven-scala-plugin + 2.15.2 + + + + compile + testCompile + + + + + + org.apache.felix + maven-bundle-plugin + ${felix.plugin.version} + true + + + + + + + + org.scala-lang + scala-library + ${scala.version} + + + org.scala-lang + scala-compiler + ${scala.version} + + + org.scalamodules + scalamodules.core + ${scalamodules.version} + + + + + From 4bb0efa4df8d1869824ae2ffe2a281ebfcdfa92b Mon Sep 17 00:00:00 2001 From: Guillaume Yziquel Date: Wed, 18 Apr 2012 11:05:42 +0200 Subject: [PATCH 29/29] Version typo. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 55f88c1..c4d3e31 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.fusesource.slang parent pom - 1.0.0.SNAPSHOT + 1.0.0-SNAPSHOT Slang 2010