diff options
author | Egil Moeller <egil.moller@freecode.no> | 2010-03-21 23:33:06 +0100 |
---|---|---|
committer | Egil Moeller <egil.moller@freecode.no> | 2010-03-21 23:33:06 +0100 |
commit | d56b9b3b82cdebcaeb00eec0fcb4326ad21adaa8 (patch) | |
tree | b1dfe31956f3fc86e3408f1efac5e12acf65b11a /trunk/infrastructure/net.appjet.bodylock | |
parent | c1894c8e0a52f4e3d2f89fa92f0066bbf0fcf1b1 (diff) | |
parent | 103d4926ae6c61824dc0b48be7bf66f08830ed47 (diff) | |
download | etherpad-d56b9b3b82cdebcaeb00eec0fcb4326ad21adaa8.tar.gz etherpad-d56b9b3b82cdebcaeb00eec0fcb4326ad21adaa8.tar.bz2 etherpad-d56b9b3b82cdebcaeb00eec0fcb4326ad21adaa8.zip |
Merge branch 'master' of git@github.com:ether/pad
Diffstat (limited to 'trunk/infrastructure/net.appjet.bodylock')
-rw-r--r-- | trunk/infrastructure/net.appjet.bodylock/bodylock.scala | 291 | ||||
-rw-r--r-- | trunk/infrastructure/net.appjet.bodylock/compressor.scala | 269 |
2 files changed, 0 insertions, 560 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")); - } - } -} diff --git a/trunk/infrastructure/net.appjet.bodylock/compressor.scala b/trunk/infrastructure/net.appjet.bodylock/compressor.scala deleted file mode 100644 index 5041787..0000000 --- a/trunk/infrastructure/net.appjet.bodylock/compressor.scala +++ /dev/null @@ -1,269 +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 java.io.{StringWriter, StringReader} -import net.appjet.common.util.BetterFile; - -object compressor { - def compress(code: String): String = { - import yuicompressor.org.mozilla.javascript.{ErrorReporter, EvaluatorException}; - object MyErrorReporter extends ErrorReporter { - def warning(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int) { - if (message startsWith "Try to use a single 'var' statement per scope.") return; - if (line < 0) System.err.println("\n[WARNING] " + message); - else System.err.println("\n[WARNING] " + line + ':' + lineOffset + ':' + message); - } - def error(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int) { - if (line < 0) System.err.println("\n[ERROR] " + message); - else System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message); - java.lang.System.exit(1); - } - def runtimeError(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int): EvaluatorException = { - error(message, sourceName, line, lineSource, lineOffset); - return new EvaluatorException(message); - } - } - - val munge = true; - val verbose = false; - val optimize = true; - val wrap = true; - val compressor = new com.yahoo.platform.yui.compressor.JavaScriptCompressor(new StringReader(code), MyErrorReporter); - val writer = new StringWriter; - compressor.compress(writer, if (wrap) 100 else -1, munge, verbose, true, optimize); - writer.toString; - } - - def main(args: Array[String]) { - for (fname <- args) { - try { - val src = BetterFile.getFileContents(fname); - val obfSrc = compress(src); - val fw = (new java.io.FileWriter(new java.io.File(fname))); - fw.write(obfSrc, 0, obfSrc.length); - fw.close(); - } catch { - case e => { - println("Failed to compress: "+fname+". Quitting."); - e.printStackTrace(); - System.exit(1); - } - } - } - } -} - - -// ignore these: - -// import java.io._; - -// def doMake { - -// lazy val isEtherPad = (args.length >= 2 && args(1) == "etherpad"); -// lazy val isNoHelma = (args.length >= 2 && args(1) == "nohelma"); - -// def getFile(path:String): String = { -// val builder = new StringBuilder(1000); -// val reader = new BufferedReader(new FileReader(path)); -// val buf = new Array[Char](1024); -// var numRead = 0; -// while({ numRead = reader.read(buf); numRead } != -1) { -// builder.append(buf, 0, numRead); -// } -// reader.close; -// return builder.toString; -// } - -// def putFile(str: String, path: String): Unit = { -// val writer = new FileWriter(path); -// writer.write(str); -// writer.close; -// } - -// def writeToString(func:(Writer=>Unit)): String = { -// val writer = new StringWriter; -// func(writer); -// return writer.toString; -// } - -// def compressJS(code: String, wrap: Boolean): String = { -// import org.mozilla.javascript.{ErrorReporter, EvaluatorException}; -// object MyErrorReporter extends ErrorReporter { -// def warning(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int) { -// if (message startsWith "Try to use a single 'var' statement per scope.") return; -// if (line < 0) System.err.println("\n[WARNING] " + message); -// else System.err.println("\n[WARNING] " + line + ':' + lineOffset + ':' + message); -// } -// def error(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int) { -// if (line < 0) System.err.println("\n[ERROR] " + message); -// else System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message); -// } -// def runtimeError(message:String, sourceName:String, line:Int, lineSource:String, lineOffset:Int): EvaluatorException = { -// error(message, sourceName, line, lineSource, lineOffset); -// return new EvaluatorException(message); -// } -// } - -// val munge = true; -// val verbose = false; -// val optimize = true; -// val compressor = new com.yahoo.platform.yui.compressor.JavaScriptCompressor(new StringReader(code), MyErrorReporter); -// return writeToString(compressor.compress(_, if (wrap) 100 else -1, munge, verbose, true, !optimize)); -// } - -// def compressCSS(code: String, wrap: Boolean): String = { -// val compressor = new com.yahoo.platform.yui.compressor.CssCompressor(new StringReader(code)); -// return writeToString(compressor.compress(_, if (wrap) 100 else -1)); -// } - -// import java.util.regex.{Pattern, Matcher, MatchResult}; - -// def stringReplace(orig: String, regex: String, groupReferences:Boolean, func:(MatchResult=>String)): String = { -// val buf = new StringBuffer; -// val m = Pattern.compile(regex).matcher(orig); -// while (m.find) { -// var str = func(m); -// if (! groupReferences) { -// str = str.replace("\\", "\\\\").replace("$", "\\$"); -// } -// m.appendReplacement(buf, str); -// } -// m.appendTail(buf); -// return buf.toString; -// } - -// def stringToExpression(str: String): String = { -// val contents = str.replace("\\", "\\\\").replace("'", "\\'").replace("<", "\\x3c").replace("\n", "\\n"). -// replace("\r", "\\n").replace("\t", "\\t"); -// return "'"+contents+"'"; -// } - -// val srcDir = "www"; -// val destDir = "build"; -// var code = getFile(srcDir+"/ace2_outer.js"); - -// val useCompression = true; //if (isEtherPad) false else true; - -// code = stringReplace(code, "\\$\\$INCLUDE_([A-Z_]+)\\([\"']([^\"']+)[\"']\\)", false, (m:MatchResult) => { -// val includeType = m.group(1); -// val path = m.group(2); -// includeType match { -// case "JS" => { -// var subcode = getFile(srcDir+"/"+path); -// subcode = subcode.replaceAll("var DEBUG=true;//\\$\\$[^\n\r]*", "var DEBUG=false;"); -// if (useCompression) subcode = compressJS(subcode, false); -// "('<script type=\"text/javascript\">//<!--\\n'+" + stringToExpression(subcode) + -// "+'//-->\\n</script>')"; -// } -// case "CSS" => { -// var subcode = getFile(srcDir+"/"+path); -// if (useCompression) subcode = compressCSS(subcode, false); -// "('<style type=\"text/css\">'+" + stringToExpression(subcode) + "+'</style>')"; -// } -// case "JS_Q" => { -// var subcode = getFile(srcDir+"/"+path); -// subcode = subcode.replaceAll("var DEBUG=true;//\\$\\$[^\n\r]*", "var DEBUG=false;"); -// if (useCompression) subcode = compressJS(subcode, false); -// "('(\\'<script type=\"text/javascript\">//<!--\\\\n\\'+'+" + -// stringToExpression(stringToExpression(subcode)) + -// "+'+\\'//-->\\\\n\\\\x3c/script>\\')')"; -// } -// case "CSS_Q" => { -// var subcode = getFile(srcDir+"/"+path); -// if (useCompression) subcode = compressCSS(subcode, false); -// "('(\\'<style type=\"text/css\">\\'+'+" + stringToExpression(stringToExpression(subcode)) + -// "+'+\\'\\\\x3c/style>\\')')"; -// } -// case ("JS_DEV" | "CSS_DEV") => "''"; -// case ("JS_Q_DEV" | "CSS_Q_DEV") => "'\\'\\''"; -// case _ => "$$INCLUDE_"+includeType+"(\"../www/"+path+"\")"; -// } -// }); - -// if (useCompression) code = compressJS(code, true); - -// putFile(code, destDir+"/ace2bare.js"); - -// var wrapper = getFile(srcDir+"/ace2_wrapper.js"); -// if (useCompression) wrapper = compressJS(wrapper, true); -// putFile(wrapper+"\n"+code, destDir+"/ace2.js"); - -// var index = getFile(srcDir+"/index.html"); -// index = index.replaceAll("<!--\\s*DEBUG\\s*-->\\s*([\\s\\S]+?)\\s*<!--\\s*/DEBUG\\s*-->", ""); -// index = index.replaceAll("<!--\\s*PROD:\\s*([\\s\\S]+?)\\s*-->", "$1"); -// putFile(index, destDir+"/index.html"); - -// putFile(getFile(srcDir+"/testcode.js"), destDir+"/testcode.js"); - -// def copyFile(fromFile: String, toFile: String) { -// if (0 != Runtime.getRuntime.exec("cp "+fromFile+" "+toFile).waitFor) { -// printf("copy failed (%s -> %s).\n", fromFile, toFile); -// } -// } - -// if (isEtherPad) { -// copyFile("build/ace2.js", "../../../etherpad/src/static/js/ace.js"); -// val easysync = getFile(srcDir+"/easy_sync.js"); -// putFile(easysync, "../../../etherpad/src/etherpad/collab/easysync.js"); -// } -// else if (! isNoHelma) { -// copyFile("build/ace2.js", "../helma_apps/appjet/protectedStatic/js/ace.js"); -// } -// } - -// def remakeLoop { - -// def getStamp: Long = { -// return new java.io.File("www").listFiles. -// filter(! _.getName.endsWith("~")). -// filter(! _.getName.endsWith("#")). -// filter(! _.getName.startsWith(".")).map(_.lastModified). -// reduceLeft(Math.max(_:Long,_:Long)); -// } - -// var madeStamp:Long = 0; -// var errorStamp:Long = 0; -// while (true) { -// Thread.sleep(500); -// val s = getStamp; -// if (s > madeStamp && s != errorStamp) { -// Thread.sleep(1000); -// if (getStamp == s) { -// madeStamp = s; -// print("Remaking... "); -// try { -// doMake; -// println("OK"); -// } -// catch { case e => { -// println("ERROR"); -// errorStamp = s; -// } } -// } -// } -// } - -// } - -// if (args.length >= 1 && args(0) == "auto") { -// remakeLoop; -// } -// else { -// doMake; -// } |