aboutsummaryrefslogtreecommitdiffstats
path: root/infrastructure/net.appjet.ajstdlib/ajstdlib.scala
diff options
context:
space:
mode:
Diffstat (limited to 'infrastructure/net.appjet.ajstdlib/ajstdlib.scala')
-rw-r--r--infrastructure/net.appjet.ajstdlib/ajstdlib.scala253
1 files changed, 253 insertions, 0 deletions
diff --git a/infrastructure/net.appjet.ajstdlib/ajstdlib.scala b/infrastructure/net.appjet.ajstdlib/ajstdlib.scala
new file mode 100644
index 0000000..8d285af
--- /dev/null
+++ b/infrastructure/net.appjet.ajstdlib/ajstdlib.scala
@@ -0,0 +1,253 @@
+/**
+ * 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.ajstdlib;
+
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.{ScheduledThreadPoolExecutor, Callable};
+import scala.collection.mutable.{HashMap, SynchronizedMap};
+
+import org.mozilla.javascript.{Context, ScriptableObject, Function, RhinoException, Scriptable};
+
+import net.appjet.oui.{SpecialJarOrNotFile, DiskLibrary, FixedDiskLibrary, VariableDiskLibrary, ExecutionContext, ExecutionContextUtils, ScopeReuseManager, config, exceptionlog};
+import net.appjet.bodylock.{BodyLock, ExecutionException};
+import net.appjet.common.util.LenientFormatter;
+
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.util.ajax.ContinuationSupport;
+
+object ajstdlib {
+ def runModuleInNewScope(cx: ExecutionContext, moduleName: String): Any = {
+ val newScope = BodyLock.subScope(cx.runner.globalScope);
+ if (! libraryExists(moduleName))
+ return Context.getUndefinedValue(); // unfortunately, returning "false" doesn't really do the right thing here.
+ try {
+ libraryExecutable(moduleName).execute(newScope);
+ } catch {
+ case e: ExecutionException => throw e;
+ case e => throw new ExecutionException("Error occurred while running module: "+moduleName, e);
+ // TODO: There was code here to print errors to the response if something didn't compile. Replace this code?
+ }
+ newScope;
+ }
+
+ private val modules = new HashMap[String, DiskLibrary] with SynchronizedMap[String, DiskLibrary];
+ private def library(name: String) = modules.getOrElseUpdate(name+".js", new VariableDiskLibrary(name+".js"));
+ private def libraryExists(name: String) = {
+ val lib = library(name);
+ // ScopeReuseManager.watch(lib);
+ lib.exists;
+ }
+ private def libraryExecutable(name: String) = {
+ val lib = library(name);
+ // ScopeReuseManager.watch(lib);
+ lib.executable;
+ }
+
+ val globalLock = new ReentrantLock();
+ val attributes = new HashMap[String, Any] with SynchronizedMap[String, Any];
+
+ def init() {
+ // any other ajstdlib initialization goes here.
+ Comet.init();
+ }
+}
+
+object printf {
+ def printf(format: String, list: Array[Object]): String = {
+// val list: Array[Object] = new Array[Object](argList.getLength)
+// for (i <- List.range(0, list.length))
+// list(i) = argList.getElement(i).getOrElse(null) match {
+// case AppVM.JSNumber(n) => n
+// case AppVM.JSString(s) => s
+// case AppVM.JSBoolean(b) => b
+// case _ => null
+// }
+ val args = list.map(x => Context.jsToJava(x, classOf[Object]));
+ try {
+ val fmt = new LenientFormatter()
+ fmt.format(format, args: _*)
+ fmt.toString()
+ } catch {
+ case e: java.util.IllegalFormatException =>
+ throw new ExecutionException("String Format Error: <tt>printf</tt> error: "+e.getMessage(), e)
+ }
+ }
+}
+
+
+import java.security.MessageDigest;
+
+object md5 {
+ def md5(input: String): String = {
+ val bytes = input.getBytes("UTF-8");
+ md5(bytes);
+ }
+ def md5(bytes: Array[byte]): String = {
+ var md = MessageDigest.getInstance("MD5");
+ var digest = md.digest(bytes);
+ var builder = new StringBuilder();
+ for (b <- digest) {
+ builder.append(Integer.toString((b >> 4) & 0xf, 16));
+ builder.append(Integer.toString(b & 0xf, 16));
+ }
+ builder.toString();
+ }
+}
+
+object execution {
+ def runAsync(ec: ExecutionContext, f: Function) {
+ ec.asyncs += f;
+ }
+
+ def executeCodeInNewScope(parentScope: Scriptable,
+ code: String, name: String,
+ startLine: Int): Scriptable = {
+ val ec = ExecutionContextUtils.currentContext;
+ val executable =
+ try {
+ BodyLock.compileString(code, name, startLine);
+ } catch {
+ case e: RhinoException =>
+ throw new ExecutionException(
+ "Failed to execute code in new scope.", e);
+ }
+ if (ec == null || ec.runner == null) {
+ Thread.dumpStack();
+ }
+ val scope = BodyLock.subScope(
+ if (parentScope != null) parentScope
+ else ec.runner.mainScope);
+ scope.setParentScope(ec.runner.mainScope);
+ executable.execute(scope);
+ scope;
+ }
+
+ def runTask(taskName: String, args: Array[Object]): AnyRef = {
+ val ec = net.appjet.oui.execution.runOutOfBand(
+ net.appjet.oui.execution.scheduledTaskExecutable,
+ "Task "+taskName,
+ Some(Map("taskName" -> taskName,
+ "taskArguments" -> args)),
+ { error =>
+ error match {
+ case e: Throwable => exceptionlog(e);
+ case _ => exceptionlog(error.toString);
+ }
+ });
+ ec.result;
+ }
+
+ def runTaskSimply(taskName: String, args: Array[Object]): AnyRef = {
+ net.appjet.oui.execution.runOutOfBandSimply(
+ net.appjet.oui.execution.scheduledTaskExecutable,
+ Some(Map("taskName" -> taskName,
+ "taskArguments" -> args)));
+ }
+
+ def wrapRunTask(taskName: String, args: Array[Object],
+ returnType: Class[_]): Function0[AnyRef] = {
+ new Function0[AnyRef] {
+ def apply = Context.jsToJava(runTaskSimply(taskName, args), returnType);
+ }
+ }
+
+ val threadpools = new HashMap[String, ScheduledThreadPoolExecutor]
+ with SynchronizedMap[String, ScheduledThreadPoolExecutor];
+
+ def createNamedTaskThreadPool(name: String, poolSize: Int) {
+ threadpools.put(name, new ScheduledThreadPoolExecutor(poolSize));
+ }
+
+ class TaskRunner(val taskName: String, args: Array[Object]) extends Callable[AnyRef] {
+ def call(): AnyRef = {
+ runTask(taskName, args);
+ }
+ }
+
+ def scheduleTaskInPool(poolName: String, taskName: String, delayMillis: Long, args: Array[Object]) = {
+ val pool = threadpools.getOrElse(poolName, throw new RuntimeException("No such task threadpool: "+poolName));
+ pool.schedule(new TaskRunner(taskName, args), delayMillis, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+
+ def shutdownAndWaitOnTaskThreadPool(poolName: String, timeoutMillis: Long) = {
+ val pool = threadpools.getOrElse(poolName, throw new RuntimeException("No such task threadpool: "+poolName));
+ pool.shutdown();
+ pool.awaitTermination(timeoutMillis, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+
+ def getContinuation(ec: ExecutionContext) = {
+ val req = ec.request.req;
+ ContinuationSupport.getContinuation(req, req).asInstanceOf[SelectChannelConnector.RetryContinuation];
+ }
+
+ def sync[T](obj: AnyRef)(block: => T): T = {
+ obj.synchronized {
+ block;
+ }
+ }
+}
+
+import javax.mail._;
+import javax.mail.internet._;
+import java.util.Properties;
+
+object email {
+ def sendEmail(toAddr: Array[String], fromAddr: String, subject: String, headers: Scriptable, content: String): String = {
+ try {
+ val badAddresses = for (a <- toAddr if (a.indexOf("@") == -1)) yield a;
+ if (badAddresses.length > 0) {
+ "The email address"+(if (badAddresses.length > 1) "es" else "")+" "+
+ badAddresses.mkString("\"", "\", \"", "\"")+" do"+(if (badAddresses.length == 1) "es" else "")+
+ " not appear to be valid.";
+ } else {
+ val debug = false;
+
+ val props = new Properties;
+ props.put("mail.smtp.host", config.smtpServerHost);
+ props.put("mail.smtp.port", config.smtpServerPort.toString());
+ if (config.smtpUser != "")
+ props.put("mail.smtp.auth", "true");
+
+ val session = Session.getInstance(props, if (config.smtpUser != "") new Authenticator {
+ override def getPasswordAuthentication() =
+ new PasswordAuthentication(config.smtpUser, config.smtpPass);
+ } else null);
+ session.setDebug(debug);
+
+ val msg = new MimeMessage(session);
+ val fromIAddr = new InternetAddress(fromAddr);
+ msg.setFrom(fromIAddr);
+ val toIAddr: Array[Address] = toAddr.map(x => (new InternetAddress(x))); // new InternetAddress(toAddr);
+ msg.setRecipients(Message.RecipientType.TO, toIAddr);
+
+ if (headers != null)
+ for (o <- headers.getIds() if o.isInstanceOf[String]) {
+ val k = o.asInstanceOf[String]
+ msg.addHeader(k, headers.get(k, headers).asInstanceOf[String]);
+ }
+
+ msg.setSubject(subject);
+ msg.setContent(content, "text/plain");
+ Transport.send(msg);
+ "";
+ }
+ } catch {
+ case e: MessagingException => { exceptionlog(e); e.printStackTrace() ; "Messaging exception: "+e.getMessage+"."; }
+ case e: Exception => { exceptionlog(e); e.printStackTrace(); "Unknown error."; }
+ }
+ }
+}