Commit 435890d5 authored by Romain Reuillon's avatar Romain Reuillon

Add osgi compatible scala interpreter.

Implement first (inefficient version) of a scala task.
parent ba7e6536
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ************************************************************* -->
<!-- *** POM Relationships *************************************** -->
<!-- ************************************************************* -->
<parent>
<groupId>org.openmole.core</groupId>
<artifactId>libraries</artifactId>
<version>0.5-SNAPSHOT</version>
</parent>
<!--Used to build the symbolic name of the bundle-->
<artifactId>org.scala-lang.scala-compiler</artifactId>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${lib.org.scala-lang.scala.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>jline</artifactId>
<version>${lib.org.scala-lang.scala.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- ************************************************************* -->
<!-- *** Project Information ************************************* -->
<!-- ************************************************************* -->
<name>${project.artifactId}</name>
<!-- ************************************************************* -->
<!-- *** Build Settings ****************************************** -->
<!-- ************************************************************* -->
<packaging>bundle</packaging>
<properties>
<libraries.export.packages>scala.tools.*</libraries.export.packages>
</properties>
</project>
......@@ -37,6 +37,7 @@
<module>net.sourceforge.jline</module>
<module>org.joda.time</module>
<module>org.scala-lang.scala-library</module>
<module>org.scala-lang.scala-compiler</module>
<module>org.apache.commons.exec</module>
<module>ccl.northwestern.edu.netlogo4</module>
<module>ccl.northwestern.edu.netlogo5</module>
......
......@@ -30,11 +30,6 @@
<artifactId>org.openmole.plugin.task.code</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.openmole.misc.pluginmanager</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<!-- ************************************************************* -->
......
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plugins</artifactId>
<groupId>org.openmole.core</groupId>
<version>0.5-SNAPSHOT</version>
</parent>
<artifactId>org.openmole.plugin.task.scala</artifactId>
<dependencies>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.openmole.misc.exception</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.openmole.core.implementation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.apache.clerezza.scala</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<!-- ************************************************************* -->
<!-- *** Project Information ************************************* -->
<!-- ************************************************************* -->
<name>${project.artifactId} ${project.version}</name>
<description />
<!-- ************************************************************* -->
<!-- *** Build Settings ****************************************** -->
<!-- ************************************************************* -->
<packaging>bundle</packaging>
</project>
/*
* Copyright (C) 2010 reuillon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openmole.plugin.task.scala
import java.io.File
import java.io.PrintWriter
import java.util.logging.Logger
import org.openmole.core.model.data.IPrototype
import org.openmole.misc.tools.io.FileUtil.fileOrdering
import org.apache.clerezza.scala.scripting.InterpreterFactory
import org.openmole.core.implementation.data.Context
import org.openmole.core.implementation.data.Variable
import org.openmole.core.implementation.task.Task
import org.openmole.core.model.data.IContext
import scala.collection.immutable.TreeSet
import scala.collection.mutable.ListBuffer
class ScalaTask(val name: String, val code: String) extends Task {
var libs = new TreeSet[File]
var imports = new ListBuffer[String]
def addImport(imp: String): this.type = {imports += imp; this}
@transient lazy val factory = new InterpreterFactory
override def process(context: IContext) = {
val interpreter = factory.createInterpreter(new PrintWriter(System.out))
context.values.foreach{v => interpreter.bind(v.prototype.name, v.value)}
interpreter.addImports(imports.toSeq: _*)
interpreter.interpret(code)
Context.empty ++ outputs.map{o => new Variable(o.prototype.asInstanceOf[IPrototype[Any]], interpreter.valueOfTerm(o.prototype.name))}
}
}
......@@ -37,6 +37,7 @@
<module>org.openmole.plugin.task.systemexec</module>
<module>org.openmole.plugin.task.code</module>
<module>org.openmole.plugin.task.groovy</module>
<module>org.openmole.plugin.task.scala</module>
<module>org.openmole.plugin.task.templatefilegenerator</module>
<module>org.openmole.plugin.task.stat</module>
<module>org.openmole.plugin.hook.file</module>
......
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>third-parties</artifactId>
<groupId>org.openmole.core</groupId>
<version>0.5-SNAPSHOT</version>
</parent>
<artifactId>org.apache.clerezza.scala</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.scala-lang.scala-compiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openmole.core</groupId>
<artifactId>org.scala-lang.scala-library</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>-->
</dependencies>
<properties>
<bundle.activator>${project.artifactId}.Activator</bundle.activator>
<eclipse.buddypolicy>global</eclipse.buddypolicy>
</properties>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
<!-- <scr:component enabled="true" immediate="true" name="org.apache.clerezza.scala.scripting.InterpreterService">
<implementation class="org.apache.clerezza.scala.scripting.InterpreterService"/>
<property name="service.pid" value="org.apache.clerezza.scala.scripting.InterpreterService"/>
</scr:component> -->
<scr:component enabled="true" immediate="true" name="org.apache.clerezza.scala.scripting.InterpreterFactory">
<implementation class="org.apache.clerezza.scala.scripting.InterpreterFactory"/>
<service servicefactory="false">
<provide interface="org.apache.clerezza.scala.scripting.InterpreterFactory"/>
</service>
<property name="service.pid" value="org.apache.clerezza.scala.scripting.InterpreterFactory"/>
</scr:component>
<scr:component enabled="true" immediate="true" name="org.apache.clerezza.scala.scripting.CompilerService">
<implementation class="org.apache.clerezza.scala.scripting.CompilerService"/>
<service servicefactory="false">
<provide interface="org.apache.clerezza.scala.scripting.CompilerService"/>
</service>
<property name="service.pid" value="org.apache.clerezza.scala.scripting.CompilerService"/>
</scr:component>
<scr:component enabled="true" immediate="true" name="org.apache.clerezza.scala.scripting.ScriptEngineFactory">
<implementation class="org.apache.clerezza.scala.scripting.ScriptEngineFactory"/>
<service servicefactory="false">
<provide interface="javax.script.ScriptEngineFactory"/>
</service>
<property name="service.pid" value="org.apache.clerezza.scala.scripting.ScriptEngineFactory"/>
<property name="javax.script.language" value="scala" />
<reference name="interpreterFactory"
interface="org.apache.clerezza.scala.scripting.InterpreterFactory"
cardinality="1..1"
bind="bindInterpreterFactory" unbind="unbindInterpreterFactory"/>
<reference name="CompilerService"
interface="org.apache.clerezza.scala.scripting.CompilerService"
cardinality="1..1"
bind="bindCompilerService" unbind="unbindCompilerService"/>
</scr:component>
<!-- <scr:component enabled="true" immediate="true" name="org.apache.clerezza.scala.scripting.Launcher">
<implementation class="org.apache.clerezza.scala.scripting.Launcher"/>
<property name="service.pid" value="org.apache.clerezza.scala.scripting.Launcher"/>
</scr:component> -->
</components>
/*
* Copyright (C) 2012 reuillon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.apache.clerezza.scala
import org.osgi.framework.BundleActivator
import org.osgi.framework.BundleContext
object Activator {
var bundleContext : BundleContext = null
}
class Activator extends BundleActivator {
override def start(componentContext: BundleContext)= {
Activator.bundleContext = componentContext
// Activator.bundleContext.addBundleListener(this)
}
override def stop(componentContext: BundleContext) = {
//currentSharedCompiler = null
// Activator.bundleContext.removeBundleListener(this)
}
}
/*
* Copyright (C) 2012 reuillon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.apache.clerezza.scala.console
import org.apache.clerezza.scala.Activator
import org.apache.clerezza.scala.scripting.BundleContextScalaCompiler
import scala.tools.nsc.Settings
import scala.tools.nsc.interpreter.AbstractFileClassLoader
import scala.tools.nsc.interpreter.IMain
import scala.tools.nsc.reporters.Reporter
class Interpreter extends IMain {
override lazy val classLoader: AbstractFileClassLoader = {
new AbstractFileClassLoader(virtualDirectory, this.getClass.getClassLoader())
}
override protected def newCompiler(settings: Settings, reporter: Reporter) = {
settings.outputDirs setSingleOutput virtualDirectory
new BundleContextScalaCompiler(Activator.bundleContext, settings, reporter)
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.scala.scripting
import org.osgi.framework.BundleContext
import org.osgi.framework.Bundle
import java.io.File
import scala.tools.nsc._;
import scala.tools.nsc.interpreter._;
import scala.tools.nsc.io.{AbstractFile, PlainFile}
import scala.tools.nsc.util._
import java.net._
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.Reporter
import scala.tools.util.PathResolver
/*
* unfortunately there seems to be no way to change the classpath, so this doesn't
* listen to BundleEvents
*/
class BundleContextScalaCompiler(bundleContext : BundleContext,
settings: Settings, reporter: Reporter) extends Global(settings, reporter) {
override lazy val classPath: ClassPath[AbstractFile] = {
val classPathOrig: ClassPath[AbstractFile] = new PathResolver(settings).result
var bundles: Array[Bundle] = bundleContext.getBundles
val classPathAbstractFiles = for (bundle <- bundles;
val url = bundle.getResource("/");
if url != null) yield {
if ("file".equals(url.getProtocol())) {
new PlainFile(new File(url.toURI()))
}
else {
BundleFS.create(bundle);
}
}
val classPaths: List[ClassPath[AbstractFile]] = (for (abstractFile <- classPathAbstractFiles)
yield {
new DirectoryClassPath(abstractFile, classPathOrig.context)
}) toList
new MergedClassPath[AbstractFile](classPathOrig :: classPaths,
classPathOrig.context)
}
override def rootLoader: LazyType = {
new loaders.JavaPackageLoader(classPath)
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.scala.scripting;
import org.osgi.framework.BundleContext
import scala.tools.nsc._;
import scala.tools.nsc.interpreter._;
import scala.tools.nsc.util._
import java.io.PrintWriter
import java.net._
import scala.tools.nsc.reporters.Reporter
class BundleContextScalaInterpreter(bundleContext : BundleContext, out: PrintWriter)
extends Interpreter(new Settings, out) {
def this(bundleContext : BundleContext) = {
this(bundleContext, new PrintWriter(System.out))
}
override lazy val classLoader: AbstractFileClassLoader = {
new AbstractFileClassLoader(virtualDirectory, this.getClass.getClassLoader())
}
override protected def newCompiler(settings: Settings, reporter: Reporter) = {
settings.outputDirs setSingleOutput virtualDirectory
new BundleContextScalaCompiler(bundleContext, settings, reporter)
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This class was taken from Sling Scala module at
* http://code.google.com/p/sling-scala/
*/
import scala.tools.nsc.io.AbstractFile
import java.io.{File, IOException, InputStream}
import java.net.URL
import org.osgi.framework.Bundle
import org.apache.clerezza.scala.scripting.Utils.{valueOrElse, nullOrElse}
package org.apache.clerezza.scala.scripting {
/**
* Implementation of {@link AbstractFile} on top of a {@link org.osgi.framework.Bundle}
*/
object BundleFS {
/**
* Create a new {@link AbstractFile} instance representing an
* {@link org.osgi.framework.Bundle}
* @param bundle
*/
def create(bundle: Bundle): AbstractFile = {
require(bundle != null, "bundle must not be null")
/**
* The superclass of FileEntry and DirEntry
*/
abstract class BundleEntry(url: URL, parent: DirEntry) extends AbstractFile {
require(url != null, "url must not be null")
lazy val (path: String, name: String) = getPathAndName(url)
lazy val fullName: String = (path::name::Nil).filter(!_.isEmpty).mkString("/")
/**
* @return null
*/
def file: File = null
//what if this is not a relative file?
def absolute = null
/**
* @return last modification time or 0 if not known
*/
def lastModified: Long =
try { url.openConnection.getLastModified }
catch { case _ => 0 }
@throws(classOf[IOException])
def container: AbstractFile =
valueOrElse(parent) {
throw new IOException("No container")
}
@throws(classOf[IOException])
def input: InputStream = url.openStream()
/**
* Not supported. Always throws an IOException.
* @throws IOException
*/
@throws(classOf[IOException])
def output = throw new IOException("not supported: output")
def delete = throw new IOException("not supported: delete")
def create = throw new IOException("not supported: create")
private def getPathAndName(url: URL): (String, String) = {
val u = url.getPath
var k = u.length
while( (k > 0) && (u(k - 1) == '/') )
k = k - 1
var j = k
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
}
class DirEntry(url: URL, parent: DirEntry) extends BundleEntry(url, parent) {
/**
* @return true
*/
def isDirectory: Boolean = true
override def iterator: Iterator[AbstractFile] = {
new Iterator[AbstractFile]() {
val dirs = bundle.getEntryPaths(fullName)
def hasNext = if (dirs != null) { dirs.hasMoreElements} else {false}
def next = {
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))
if (entryUrl == null) {
entryUrl = new URL(bundle.getResource("/"), entry)
if (entryUrl == null) {
throw new RuntimeException("Could not locate entry: "+entry+" in bundle: "+bundle)
}
}
if (entry.endsWith(".class"))
new FileEntry(entryUrl, DirEntry.this)
else
new DirEntry(entryUrl, DirEntry.this)
}
private def removeTralingSlash(s: String): String = {
if (s == null || s.length == 0) {
s
}else if (s.last == '/') {
removeTralingSlash(s.substring(0, s.length - 1))
} else {
s
}
}
}
}
def lookupName(name: String, directory: Boolean): AbstractFile = {
val entry = bundle.getEntry(fullName + "/" + name)
nullOrElse(entry) { entry =>
if (directory)
new DirEntry(entry, DirEntry.this)
else
new FileEntry(entry, DirEntry.this)
}
}
def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile = {
val entry = bundle.getEntry(fullName + "/" + name)
if (entry == null) {
throw new RuntimeException("Not yet implemented: inexistendt file")
} else {
if (directory)
new DirEntry(entry, DirEntry.this)
else
new FileEntry(entry, DirEntry.this)
}
}
}
class FileEntry(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())
override def iterator: Iterator[AbstractFile] = Iterator.empty
def lookupName(name: String, directory: Boolean): AbstractFile = null
def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile = null
}
new DirEntry(bundle.getResource("/"), null)
}
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.scala.scripting;
import java.security.AccessController
import java.security.Permission
import java.security.PrivilegedAction
import java.security.PrivilegedActionException
import java.security.PrivilegedExceptionAction
import org.apache.clerezza.scala.scripting.util.FileWrapper
import org.apache.clerezza.scala.scripting.util.GenericFileWrapperTrait
import org.apache.clerezza.scala.scripting.util.VirtualDirectoryWrapper
import org.osgi.framework.BundleActivator
import org.osgi.framework.BundleContext
import org.osgi.framework.BundleEvent
import org.osgi.framework.BundleListener
//import org.osgi.service.component.ComponentContext;
import scala.tools.nsc._;
import scala.tools.nsc.interpreter._;
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.io.VirtualDirectory
import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.util._
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.IOException
import java.io.OutputStream
import java.io.PrintWriter
import java.io.Reader
import java.net._
import org.apache.clerezza.scala.Activator
class CompileErrorsException(message: String) extends Exception(message) {
def this() = this(null)
}
class CompilePermission extends Permission("Compile Permssion") {
def getActions() = ""
def implies(p: Permission) = p.isInstanceOf[CompilePermission]
override def equals(o: Any): Boolean = o.isInstanceOf[CompilePermission]
override def hashCode = classOf[CompilePermission].hashCode
}
class CompilerService() /*extends BundleListener with BundleActivator*/ {
//protected var bundleContext : BundleContext = null;
//protected val sharedVirtualDirectory = new VirtualDirectory("(memory)", None)
protected var currentSharedCompilerOutputStream: OutputStream = null
protected val splipptingOutputStream = new OutputStream() {
def write(b: Int) {
if (currentSharedCompilerOutputStream == null) {
throw new IOException("no currentSharedCompilerOutputStream set")
}
currentSharedCompilerOutputStream.write(b)
}
}
protected val splittingPrintWriter = new PrintWriter(splipptingOutputStream, true)
protected var currentSharedCompiler: TrackingCompiler = null;
protected def sharedCompiler = {
if (currentSharedCompiler == null) {
synchronized {
if (currentSharedCompiler == null) {
currentSharedCompiler = TrackingCompiler(Activator.bundleContext, splittingPrintWriter, None)
//createCompiler(splittingPrintWriter, sharedVirtualDirectory)
}
}
}
currentSharedCompiler
}
/*override def start(componentContext: BundleContext)= {
CompilerService.bundleContext = componentContext
CompilerService.bundleContext.addBundleListener(this)
}
override def stop(componentContext: BundleContext) = {
currentSharedCompiler = null
CompilerService.bundleContext.removeBundleListener(this)
}*/
/* override def bundleChanged(event: BundleEvent) = {
currentSharedCompiler = null
}*/
def createCompiler(out: PrintWriter, outputSirectory: AbstractFile) : TrackingCompiler = {
TrackingCompiler(Activator.bundleContext, out, Some(outputSirectory))
}
def compile(sources: Array[Array[Char]]): Array[Class[_]] = {
compile(sources.toList).toArray
}
def compile(sources: List[Array[Char]]): List[Class[_]] = {
AccessController.checkPermission(new CompilePermission)
sharedCompiler.synchronized {
try {
AccessController.doPrivileged[List[Class[_]]](
new PrivilegedExceptionAction[List[Class[_]]] {
def run(): List[Class[_]] = {
val baos = new ByteArrayOutputStream
currentSharedCompilerOutputStream = baos
try {
sharedCompiler.compile(sources)
} catch {
case c: CompileErrorsException => throw new CompileErrorsException(
new String(baos.toByteArray, "utf-8"))
case e => throw e
} finally {
currentSharedCompilerOutputStream = null
}
}
})
} catch {
case e: PrivilegedActionException => throw e.getCause
case e => throw e
}
}
}
/**
* compiles a set of sources with a dedicated compiler
*/
def compileIsolated(sources: List[Array[Char]]): List[Class[_]] = {
val virtualDirectory = new VirtualDirectory("(memory)", None)
compileIsolated(sources, virtualDirectory)
}
def compileIsolated(sources: List[Array[Char]], outputDirectory: AbstractFile): List[Class[_]] = {
AccessController.checkPermission(new CompilePermission)
sharedCompiler.synchronized {
try {
AccessController.doPrivileged[List[Class[_]]](
new PrivilegedExceptionAction[List[Class[_]]] {
def run() = {
val out = new ByteArrayOutputStream
val printWriter = new PrintWriter(out)
val compiler = createCompiler(printWriter, outputDirectory)
try {
compiler.compile(sources)
} catch {
case c: CompileErrorsException => throw new CompileErrorsException(new String(out.toByteArray, "utf-8"))
case e => throw e
}
}
})
}
}
}
def compileToDir(sources: List[Array[Char]], outputDirectory: AbstractFile): List[AbstractFile] = {
AccessController.checkPermission(new CompilePermission)
sharedCompiler.synchronized {
try {
AccessController.doPrivileged[List[AbstractFile]](
new PrivilegedExceptionAction[List[AbstractFile]] {
def run() = {
val out = new ByteArrayOutputStream
val printWriter = new PrintWriter(out)
val compiler = createCompiler(printWriter, outputDirectory)
try {
compiler.compileToDir(sources)
} catch {
case c: CompileErrorsException => throw new CompileErrorsException(new String(out.toByteArray, "utf-8"))
case e => throw e
}
}
})
}
}
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.scala.scripting;
import org.osgi.framework.BundleContext
import org.osgi.framework.Bundle
import scala.tools.nsc._;
import scala.tools.nsc.interpreter._;
import scala.tools.nsc.util._
import java.io.PrintWriter
import java.net._
import org.apache.clerezza.scala.Activator
class InterpreterFactory {
def createInterpreter(out: PrintWriter) : Interpreter = {
val i = new BundleContextScalaInterpreter(Activator.bundleContext, out)
i
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.scala.scripting
import org.apache.clerezza.scala.scripting.util.FileWrapper
import org.apache.clerezza.scala.scripting.util.GenericFileWrapperTrait
import org.apache.clerezza.scala.scripting.util.SplittingDirectory
import org.apache.clerezza.scala.scripting.util.VirtualDirectoryWrapper
import org.osgi.framework.BundleContext
import scala.collection.mutable
import scala.tools.nsc._;
import scala.tools.nsc.interpreter._;
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.io.VirtualDirectory
import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.reporters.Reporter
import scala.tools.nsc.util._
import java.io.ByteArrayOutputStream
import java.io.PrintWriter
import java.net._
/** a compiler that keeps track of classes added to the directory
*/
class TrackingCompiler private (bundleContext : BundleContext,
settings: Settings, reporter: Reporter, classLoaderBuilder: () => ClassLoader,
writtenClasses: mutable.ListBuffer[AbstractFile])
extends BundleContextScalaCompiler(bundleContext : BundleContext,
settings: Settings, reporter: Reporter) {
/**
* compiles a list of classes to settings.outputDirs returning a
* the generated AbstractFiles
*/
@throws(classOf[CompileErrorsException])
def compileToDir(sources: List[Array[Char]]): List[AbstractFile] = {
writtenClasses.clear()
var i = 0
val sourceFiles: List[SourceFile] = for(chars <- sources) yield {
i = i +1;
new BatchSourceFile("<script"+i+">", chars)
}
(new Run).compileSources(sourceFiles)
if (reporter.hasErrors) {
reporter.reset
throw new CompileErrorsException;
}
writtenClasses.toList
}
/**
* compiles a list of class sources returning a list of compiled classes
*/
@throws(classOf[CompileErrorsException])
def compile(sources: List[Array[Char]]): List[Class[_]] = {
val classFiles = compileToDir(sources)
val classLoader = classLoaderBuilder()
val result: List[Class[_]] = for (classFile <- classFiles;
if (!classFile.name.contains('$'))) yield {
val path = classFile.path
val relevantPath = path.substring(path.indexOf('/')+1,path.lastIndexOf('.'))
val fqn = relevantPath.replace("/",".")
classLoader.loadClass(fqn)
}
return result
}
}
object TrackingCompiler {
private class TrackingCompilerSplittingDirectory extends SplittingDirectory
private def createClassLoader(dir: AbstractFile) = new AbstractFileClassLoader(dir, this.getClass.getClassLoader())
def apply(bundleContext : BundleContext, out: PrintWriter, outputDirectoryOption: Option[AbstractFile]) = {
val (outputDirectory, classLoaderBuilder): (AbstractFile, () => ClassLoader) = outputDirectoryOption match {
case Some(d) => (d, () => createClassLoader(d))
case None => {
val d = new TrackingCompilerSplittingDirectory
d.currentTarget = new VirtualDirectory("(memory)", None)
def createClassLoaderAndReset() = {
val r = createClassLoader(d.currentTarget)
//println("created class loader with "+(for (c <- d.currentTarget) yield c).mkString("-"))
d.currentTarget = new VirtualDirectory("(memory)", None)
r
}
(d, createClassLoaderAndReset _)
}
}
val writtenClasses: mutable.ListBuffer[AbstractFile] = mutable.ListBuffer[AbstractFile]()
val settings = {
def outputListener(abtractFile: AbstractFile) {
writtenClasses += abtractFile
}
val settings = new Settings
settings.outputDirs setSingleOutput VirtualDirectoryWrapper.wrap(outputDirectory, outputListener)
settings
}
new TrackingCompiler(bundleContext,
settings,
new ConsoleReporter(settings, null, out) {
override def printMessage(msg: String) {
out write msg
out.flush()
}
}, classLoaderBuilder, writtenClasses)
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.clerezza.scala.scripting
/**
* General purpose utility functions
*/
object Utils {
/**
* Evaluate <code>f</code> on <code>s</code> if <code>s</code> is not null.
* @param s
* @param f
* @return <code>f(s)</code> if s is not <code>null</code>, <code>null</code> otherwise.
*/
protected[scripting] def nullOrElse[S, T](s: S)(f: S => T): T =
if (s == null) null.asInstanceOf[T]
else f(s)
/**
* @param t
* @param default
* @return <code>t</code> or <code>default</code> if <code>null</code>.
*/
protected[scripting] def valueOrElse[T](t: T)(default: => T) =
if (t == null) default
else t
/**
* Converts a value into an Option.
* @param value
* @returns <code>Some(value)</code> if value is not <code>null</code>,
* <code>None</code> otherwise.
*/
protected[scripting] def option[T](value: T): Option[T] =
if (null == value) None else Some(value)
}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.apache.clerezza.scala.scripting.util
import scala.tools.nsc.io.AbstractFile
class FileWrapper(val wrapped: AbstractFile, val childWrapper: (AbstractFile) => AbstractFile) extends AbstractFile with GenericFileWrapperTrait {
/** overriding this hgere rather than in the trait as this is a var in VirtualDirectory
*/
def lastModified = {
wrapped.lastModified
}
override protected def unsupported(msg: String) = {
println("unsupported!")
try {
super.unsupported(msg)
} catch {
case e => e.printStackTrace(); throw e
}
}
}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.apache.clerezza.scala.scripting.util
import scala.tools.nsc.io.AbstractFile
trait GenericFileWrapperTrait extends AbstractFile with Wrapper[AbstractFile] {
override def lookupNameUnchecked(name: String,directory: Boolean) = {
childWrapper(wrapped.lookupNameUnchecked(name, directory))
}
override def lookupName(name: String,directory: Boolean) = {
wrapped.lookupName(name, directory)
}
override def iterator = {
//TODO wrap
wrapped.iterator
}
override def output = {
wrapped.output
}
override def input = {
wrapped.input
}
override def isDirectory = {
wrapped.isDirectory
}
override def delete = {
wrapped.delete
}
override def create = {
wrapped.create
}
override def file = {
wrapped.file
}
override def container = {
childWrapper(wrapped.container)
}
override def absolute = {
childWrapper(wrapped.absolute)
}
override def path = {
wrapped.path
}
override def name = {
wrapped.name
}
override def sizeOption = {
wrapped.sizeOption
}
override def lookupPath(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPath(path, directory))
}
override def lookupPathUnchecked(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPathUnchecked(path, directory))
}
override def fileNamed(name: String): AbstractFile = {
childWrapper(wrapped.fileNamed(name))
}
override def subdirectoryNamed(name: String): AbstractFile = {
childWrapper(wrapped.subdirectoryNamed(name))
}
}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.apache.clerezza.scala.scripting.util
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.io.VirtualDirectory
class SplittingDirectory()
extends VirtualDirectory(null, None) with GenericFileWrapperTrait {
var currentTarget: VirtualDirectory = null
protected def wrapped: VirtualDirectory = {
if (currentTarget == null) {
throw new RuntimeException("No current Target set, SplittingDirectory not usable")
}
currentTarget
}
private def wrap(f: AbstractFile): AbstractFile = {
f match {
case d: VirtualDirectory => new VirtualDirectoryWrapper(d, wrap) {
override def output = d.output
}
case o => new FileWrapper(o, wrap)
}
}
val childWrapper: (AbstractFile) => AbstractFile = wrap
//lastModified = wrapped.lastModified
override def output = {
wrapped.asInstanceOf[VirtualDirectory].output
}
override def input = {
wrapped.asInstanceOf[VirtualDirectory].input
}
override def file = {
wrapped.asInstanceOf[VirtualDirectory].file
}
override def container = {
wrapped.asInstanceOf[VirtualDirectory].container
}
override def absolute = {
wrapped.asInstanceOf[VirtualDirectory].absolute
}
override val name = "(splitting)"
override def lookupPath(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPath(path, directory))
}
override def lookupPathUnchecked(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPathUnchecked(path, directory))
}
}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.apache.clerezza.scala.scripting.util
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.io.VirtualDirectory
class VirtualDirectoryWrapper(val wrapped: AbstractFile,
val childWrapper: (AbstractFile) => AbstractFile) extends VirtualDirectory(null, None)
with GenericFileWrapperTrait {
lastModified =wrapped.lastModified
override def output = {
wrapped.asInstanceOf[VirtualDirectory].output
}
override def input = {
wrapped.asInstanceOf[VirtualDirectory].input
}
override def file = {
wrapped.asInstanceOf[VirtualDirectory].file
}
override def container = {
wrapped.asInstanceOf[VirtualDirectory].container
}
override def absolute = {
wrapped.asInstanceOf[VirtualDirectory].absolute
}
override val name = {
wrapped.name
}
override def lookupPath(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPath(path, directory))
}
override def lookupPathUnchecked(path: String, directory: Boolean): AbstractFile = {
childWrapper(wrapped.lookupPathUnchecked(path, directory))
}
}
object VirtualDirectoryWrapper {
trait VirtualDirectoryFlavour extends VirtualDirectoryWrapper {
abstract override def output = {
println("unexpected call to output "+name)
super.output
}
}
def wrap(f: AbstractFile, outputListenerParam: (AbstractFile) => Unit): AbstractFile = {
def innerWrap(f: AbstractFile) = wrap(f, outputListenerParam)
f match {
case d: VirtualDirectory => new VirtualDirectoryWrapper(d,
innerWrap)
with LoggingFileWrapper with VirtualDirectoryFlavour {
override def output = d.output
val outputListener = outputListenerParam
}
case o => new FileWrapper(o, innerWrap) with LoggingFileWrapper {
val outputListener = outputListenerParam
}
}
}
trait LoggingFileWrapper extends GenericFileWrapperTrait {
val outputListener: (AbstractFile) => Unit
abstract override def output = {
outputListener(this)
super.output
}
}
}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.apache.clerezza.scala.scripting.util
trait Wrapper[T] {
protected def wrapped: T
protected def childWrapper: (T) => T
}
......@@ -17,6 +17,7 @@
<modules>
<module>com.ice.tar</module>
<module>org.apache.clerezza.scala</module>
</modules>
<!-- ************************************************************* -->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment