diff options
author | Egil Moeller <egil.moller@freecode.no> | 2010-03-22 00:16:53 +0100 |
---|---|---|
committer | Egil Moeller <egil.moller@freecode.no> | 2010-03-22 00:16:53 +0100 |
commit | fc00cfedd6c25d1634a1e0d28a7b7bc5f42e1cd7 (patch) | |
tree | 928419d6bfe794865e4b8f0634bd792f795c4b8a /trunk/infrastructure/net.appjet.bodylock/bodylock.scala | |
parent | 0fdab3db005c4fa31fb8306b573c0b35073d3e56 (diff) | |
parent | d56b9b3b82cdebcaeb00eec0fcb4326ad21adaa8 (diff) | |
download | etherpad-fc00cfedd6c25d1634a1e0d28a7b7bc5f42e1cd7.tar.gz etherpad-fc00cfedd6c25d1634a1e0d28a7b7bc5f42e1cd7.tar.xz etherpad-fc00cfedd6c25d1634a1e0d28a7b7bc5f42e1cd7.zip |
Merge branch 'master' into plugin-framework
Diffstat (limited to 'trunk/infrastructure/net.appjet.bodylock/bodylock.scala')
-rw-r--r-- | trunk/infrastructure/net.appjet.bodylock/bodylock.scala | 291 |
1 files changed, 0 insertions, 291 deletions
diff --git a/trunk/infrastructure/net.appjet.bodylock/bodylock.scala b/trunk/infrastructure/net.appjet.bodylock/bodylock.scala deleted file mode 100644 index e24d55c..0000000 --- a/trunk/infrastructure/net.appjet.bodylock/bodylock.scala +++ /dev/null @@ -1,291 +0,0 @@ -/** - * Copyright 2009 Google Inc. - * - * 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 net.appjet.bodylock; - -import net.appjet.common.rhino.rhinospect; - -import scala.collection.mutable.{SynchronizedMap, ArrayBuffer, HashMap}; - -import org.mozilla.javascript.{Context, Scriptable, ScriptableObject, Script, JavaScriptException, NativeJavaObject, WrappedException, IdScriptableObject}; - -trait Executable { - def execute(scope: Scriptable): Object; -} - -trait JSStackFrame { - def errorLine: Int; // 1-indexed. - def errorContext(rad: Int): (Int, Int, Seq[String]); // 1-indexed - def name: String; -} - -class ExecutionException(message: String, cause: Throwable) extends RuntimeException(message, cause) { - def this(message: String) = this(message, null); -} - -class JSRuntimeException(val message: String, val cause: Throwable) extends ExecutionException(message, cause) { - private val i_frames: Seq[JSStackFrame] = if (cause == null) List() else { - val ab = new ArrayBuffer[JSStackFrame]; - for (elt <- cause.getStackTrace() if (elt.getFileName != null && BodyLock.map.filter(_.contains(elt.getFileName)).isDefined && elt.getLineNumber >= 0)) { - ab += new JSStackFrame { - val errorLine = elt.getLineNumber; - val name = elt.getFileName; - val code = BodyLock.map.getOrElse(Map[String, String]()).getOrElse(elt.getFileName, "").split("\n"); // 0-indexed. - def errorContext(rad: Int) = { - val start_i = Math.max(errorLine-rad, 1)-1; - val end_i = Math.min(errorLine+rad, code.length)-1; - (start_i+1, end_i+1, code.slice(start_i, end_i+1)); - } - } - } - ab; - } - def frames = i_frames; -} - -class JSCompileException(message: String, cause: org.mozilla.javascript.EvaluatorException) extends JSRuntimeException(message, cause) { - override val frames = - List(new JSStackFrame { - val errorLine = cause.lineNumber(); - val name = cause.sourceName(); - val code = BodyLock.map.getOrElse(Map[String, String]()).getOrElse(cause.sourceName(), "").split("\n"); // 0-indexed. - def errorContext(rad: Int) = { - val start_i = Math.max(errorLine-rad, 1)-1; - val end_i = Math.min(errorLine+rad, code.length)-1; - (start_i+1, end_i+1, code.slice(start_i, end_i+1)); - } - }).concat(List(super.frames: _*)); -} - -private[bodylock] class InnerExecutable(val code: String, val script: Script) extends Executable { - def execute(scope: Scriptable) = try { - BodyLock.runInContext { cx => - script.exec(cx, scope); - } - } catch { - case e: Throwable => { - val orig = BodyLock.unwrapExceptionIfNecessary(e); - orig match { - case e: JSRuntimeException => throw e; - case e: org.mortbay.jetty.RetryRequest => throw e; - case _ => throw new JSRuntimeException("Error while executing: "+orig.getMessage, orig); - } - } - } - - override def toString() = - rhinospect.dumpFields(script, 1, ""); -} - -object CustomContextFactory extends org.mozilla.javascript.ContextFactory { - val wrapFactory = new org.mozilla.javascript.WrapFactory { - setJavaPrimitiveWrap(false); // don't wrap strings, numbers, booleans - } - - class CustomContext() extends Context() { - setWrapFactory(wrapFactory); - } - - override def makeContext(): Context = new CustomContext(); -} - -object BodyLock { - var map: Option[SynchronizedMap[String, String]] = None; - - def runInContext[E](expr: Context => E): E = { - val cx = CustomContextFactory.enterContext(); - try { - expr(cx); - } finally { - Context.exit(); - } - } - - def newScope = runInContext { cx => - cx.initStandardObjects(null, true); - } - def subScope(scope: Scriptable) = runInContext { cx => - val newObj = cx.newObject(scope).asInstanceOf[ScriptableObject]; - newObj.setPrototype(scope); - newObj.setParentScope(null); - newObj; - } - - def evaluateString(scope: Scriptable, source: String, sourceName: String, - lineno: Int /*, securityDomain: AnyRef = null */) = runInContext { cx => - cx.evaluateString(scope, source, sourceName, lineno, null); - } - def compileString(source: String, sourceName: String, lineno: Int - /*, securityDomain: AnyRef = null */) = runInContext { cx => - map.foreach(_(sourceName) = source); - try { - new InnerExecutable(source, compileToScript(source, sourceName, lineno)); - } catch { - case e: org.mozilla.javascript.EvaluatorException => { - throw new JSCompileException(e.getMessage(), e); - } - } - } - - private val classId = new java.util.concurrent.atomic.AtomicInteger(0); - - private def compileToScript(source: String, sourceName: String, lineNumber: Int): Script = { - val className = "JS$"+sourceName.replaceAll("[^a-zA-Z0-9]", "\\$")+"$"+classId.incrementAndGet(); - compilationutils.compileToScript(source, sourceName, lineNumber, className); - } - - def executableFromBytes(bytes: Array[byte], className: String) = - new InnerExecutable("(source not available)", compilationutils.bytesToScript(bytes, className)); - - def unwrapExceptionIfNecessary(e: Throwable): Throwable = { - e match { - case e: JavaScriptException => e.getValue() match { - case njo: NativeJavaObject => Context.jsToJava(njo, classOf[Object]) match { - case e: Throwable => e; - case _ => e; - } - case ne: IdScriptableObject => new JSRuntimeException("Error: "+ne.get("message", ne), e); - case t: Throwable => t; - case _ => e; - } - case e: WrappedException => unwrapExceptionIfNecessary(e.getWrappedException()); - case _ => e; - } - } -} - -private[bodylock] object compilationutils { - class Loader(parent: ClassLoader) extends ClassLoader(parent) { - def this() = this(getClass.getClassLoader); - def defineClass(className: String, bytes: Array[Byte]): Class[_] = { - // call protected method - defineClass(className, bytes, 0, bytes.length); - } - } - - def compileToBytes(source: String, sourceName: String, lineNumber: Int, - className: String): Array[Byte] = { - val environs = new org.mozilla.javascript.CompilerEnvirons; - BodyLock.runInContext(environs.initFromContext(_)); - environs.setGeneratingSource(false); - val compiler = new org.mozilla.javascript.optimizer.ClassCompiler(environs); - - // throws EvaluatorException - val result:Array[Object] = - compiler.compileToClassFiles(source, sourceName, lineNumber, className); - - // result[0] is class name, result[1] is class bytes - result(1).asInstanceOf[Array[Byte]]; - } - - def compileToScript(source: String, sourceName: String, lineNumber: Int, - className: String): Script = { - bytesToScript(compileToBytes(source, sourceName, lineNumber, className), className); - } - - def bytesToScript(bytes: Array[Byte], className: String): Script = { - (new Loader()).defineClass(className, bytes).newInstance.asInstanceOf[Script]; - } -} - - -import java.io.File; -import scala.collection.mutable.HashMap; -import net.appjet.common.util.BetterFile; -import net.appjet.common.cli._; - -object Compiler { - val optionsList = Array( - ("destination", true, "Destination for class files", "path"), - ("cutPrefix", true, "Drop this prefix from files", "path"), - ("verbose", false, "Print debug information", "") - ); - val chosenOptions = new HashMap[String, String]; - val options = - for (opt <- optionsList) yield - new CliOption(opt._1, opt._3, if (opt._2) Some(opt._4) else None) - -// var o = new Options; -// for (m <- optionsList) { -// o.addOption({ -// if (m._2) { -// withArgName(m._4); -// hasArg(); -// } -// withDescription(m._3); -// // withLongOpt(m.getName()); -// create(m._1); -// }); -// } -// o; -// } - - var verbose = true; - def vprintln(s: String) { - if (verbose) println(s); - } - - def printUsage() { - println((new CliParser(options)).usage); - } - def extractOptions(args0: Array[String]) = { - val parser = new CliParser(options); - val (opts, args) = - try { - parser.parseOptions(args0); - } catch { - case e: ParseException => { - println("error: "+e.getMessage()); - printUsage(); - System.exit(1); - null; - } - } - for ((k, v) <- opts) { - chosenOptions(k) = v; - } - args - } - def compileSingleFile(src: File, dst: File) { - val source = BetterFile.getFileContents(src); - vprintln("to: "+dst.getPath()); - val classBytes = compilationutils.compileToBytes(source, src.getName(), 1, dst.getName().split("\\.")(0)); - - val fos = new java.io.FileOutputStream(dst); - fos.write(classBytes); - } - - def main(args0: Array[String]) { - // should contain paths, relative to PWD, of javascript files to compile. - val args = extractOptions(args0); - val dst = chosenOptions("destination"); - val pre = chosenOptions.getOrElse("cutPrefix", ""); - verbose = chosenOptions.getOrElse("verbose", "false") == "true"; - for (p <- args) { - val srcFile = new File(p); - if (srcFile.getParent() != null && ! srcFile.getParent().startsWith(pre)) - throw new RuntimeException("srcFile "+srcFile.getPath()+" doesn't start with "+pre); - val parentDir = - if (srcFile.getParent() != null) { - new File(dst+"/"+srcFile.getParent().substring(pre.length)); - } else { - new File(dst); - } - parentDir.mkdirs(); - compileSingleFile(srcFile, new File(parentDir.getPath()+"/JS$"+srcFile.getName().split("\\.").reverse.drop(1).reverse.mkString(".").replaceAll("[^a-zA-Z0-9]", "\\$")+".class")); - } - } -} |