aboutsummaryrefslogtreecommitdiffstats
path: root/infrastructure/framework-src/preamble.js
diff options
context:
space:
mode:
Diffstat (limited to 'infrastructure/framework-src/preamble.js')
-rw-r--r--infrastructure/framework-src/preamble.js325
1 files changed, 325 insertions, 0 deletions
diff --git a/infrastructure/framework-src/preamble.js b/infrastructure/framework-src/preamble.js
new file mode 100644
index 0000000..40f6845
--- /dev/null
+++ b/infrastructure/framework-src/preamble.js
@@ -0,0 +1,325 @@
+/**
+ * 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.
+ */
+
+// appjetContext.cache_requestCache()._t_start = (new Date()).valueOf();
+var _appjethidden_ = {};
+var serverhandlers = { tasks: {} };
+
+/*
+ * @overview
+ *
+ * AppJet standard library preamble.
+ *
+ * This is run at the beginning of every request, right after all
+ * native calls are loaded into appjetContext. This file is run
+ * in the same scope as the app, the global scope, which is also
+ * accessible from all modules.
+ */
+
+//----------------------------------------------------------------
+// delete pesky rhino built-in string stuff
+//----------------------------------------------------------------
+(function() {
+ // rhino strings come with a bunch of random "html helpers"
+ // that we don't want
+ var htmlStuff = ["bold", "italics", "fixed", "strike",
+ "small", "big", "sub", "fontsize", "fontcolor", "link",
+ "anchor", "sup", "blink"];
+ for(var i in htmlStuff) {
+ delete String.prototype[htmlStuff[i]];
+ }
+})();
+
+//----------------------------------------------------------------
+// module implementation
+//----------------------------------------------------------------
+
+(function(globalScope) {
+
+ //----------------------------------------------------------------
+ // Utility Functions
+ //----------------------------------------------------------------
+ function appjetContext() {
+ return net.appjet.oui.ExecutionContextUtils.currentContext();
+ }
+ function internalError(m) {
+ throw new Error("AppJet Internal Error: "+m);
+ }
+ function apiError(m) {
+ throw new Error("AppJet API Error: "+m);
+ }
+ function newScope() {
+ var o = new Object();
+ o.__parent__ = null;
+ o.__proto__ = globalScope;
+ return o;
+ }
+ _appjethidden_._debugMessage = function(m) {
+ //java.lang.System.out.println(m);
+ };
+ var debug = _appjethidden_._debugMessage;
+ function copySymbol(srcName, symName, src, dst, dstSymName) {
+ if (!src.hasOwnProperty(symName)) {
+ apiError("Import error: module \""+srcName+"\" does not contain the symbol \""+symName+"\".");
+ }
+ if (symName.charAt(0) == '_') {
+ apiError("Import error: cannot import symbol \""+symName+"\" because it is private (begins with _)");
+ }
+ debug(" | copying symbol ["+symName+"]");
+ dst[dstSymName || symName] = src[symName];
+ }
+ function copyPublicSymbols(src, dst) {
+ for (k in src) {
+ if (src.hasOwnProperty(k) && (k.length > 0) && (k.charAt(0) != '_')) {
+ copySymbol('', k, src, dst);
+ }
+ }
+ }
+
+ // Module import cache... hidden from other scopes.
+ var moduleObjects = {};
+ var modulesBeingLoaded = {};
+
+ /*--------------------------------------------------------------------------------
+ * loadModule():
+ * Evaluates moduleName in its own private scope, then copies its public identifiers
+ * into a new scope. This new scope is stored in moduleObjects[moduleName] for future use
+ * by import()s.
+ *
+ * If moduleName is currently being loaded (because we are in the middle of another loadModule()
+ * higher in the call stack), then this function does noething, on the assumption
+ * that moduleName will eventually be loaded anyway. Therefore, it cannot be assumed that
+ * moduleName is done being loaded when loadModule() returns, only that it eventually will be
+ * loaded when all loadModule calls return up the call stack.
+ *--------------------------------------------------------------------------------*/
+ function loadModule(moduleName) {
+ if (modulesBeingLoaded[moduleName]) {
+ // This is OK. The module will be loaded eventually.
+ return;
+ }
+ if (moduleObjects[moduleName]) {
+ return;
+ }
+ modulesBeingLoaded[moduleName] = true;
+ try {
+ debug("loadModule: "+moduleName);
+
+ var modulePrivateScope =
+ Packages.net.appjet.ajstdlib.ajstdlib.runModuleInNewScope(
+ appjetContext(), moduleName.split('.').join('/'));
+
+ if (!modulePrivateScope) {
+ // moduleName is not a module. This is normal, because when someone calls
+ // import("foo.bar"), we dont know if bar is a module or an identifier in the foo module.
+ delete modulesBeingLoaded[moduleName];
+ return;
+ }
+ // Thinking this could be useful:
+ // modulePrivateScope['__MODULE_NAME__'] = moduleName;
+ var moduleObj = newScope();
+ copyPublicSymbols(modulePrivateScope, moduleObj);
+ moduleObjects[moduleName] = moduleObj;
+ } finally {
+ delete modulesBeingLoaded[moduleName];
+ }
+ }
+
+ /*--------------------------------------------------------------------------------
+ * importSingleModule():
+ *
+ * Takes a single moduleName (like "etherpad.foo.bar.baz") and creates the identifier "baz"
+ * in dstScope, referencing the module etherpad.foo.bar.baz.
+ *
+ * This function is called one or more times by importPath(). Note that importPath() is more like
+ * the import() function that modules ses.
+ *--------------------------------------------------------------------------------*/
+ function importSingleModule(moduleName, dstScope) {
+ debug("importSingleModule: "+moduleName);
+ if (typeof(moduleName) != 'string') {
+ apiError("modules should be referred to with string, not "+typeof(moduleName));
+ }
+
+ var moduleObj = moduleObjects[moduleName]; // public module scope
+ if (!moduleObj) {
+ return false;
+ }
+
+ var importedName = moduleName;
+ if (importedName.indexOf(".") != -1) {
+ importedName = importedName.split(".").slice(-1)[0];
+ }
+ dstScope[importedName] = moduleObj;
+ return true;
+ }
+
+ /*--------------------------------------------------------------------------------
+ * importPath():
+ * takes a modulePath (like "a.b.c.{d,e,f}" or "a.b.*" or just "a.b" or "a") and
+ * repeatedly calls importSingleModule() as necessary, copying public symbols into dst.
+ *--------------------------------------------------------------------------------*/
+ function importPath(modulePath, dst) {
+ debug("importPath: "+modulePath);
+
+ // Two possibilties:
+ // 1. import the exact module and that's it.
+ //
+ // 2. module contains a "." and we need to import up to the
+ // last ., and then import a name (or set of names) from it.
+
+ // first try case 1:
+ var ok = importSingleModule(modulePath, dst);
+ if (ok) {
+ return;
+ }
+
+ if (modulePath.indexOf(".") == -1) {
+ throw new Error("Module does not exist: "+modulePath);
+ }
+
+ // now try case 2:
+ var tempDst = newScope();
+ var moduleName = modulePath.split('.').slice(0, -1).join('.');
+ var importedName = modulePath.split('.').slice(-1)[0];
+ var lastName = modulePath.split('.').slice(-2, -1)[0];
+
+ ok = importSingleModule(moduleName, tempDst);
+ if (!ok) {
+ throw new Error("Neither module exists: "+moduleName+", "+modulePath);
+ }
+
+ if (!tempDst[lastName]) {
+ internalError("import failed for "+moduleName+"|"+importedName+". This could be an appjet bug.");
+ }
+ if (importedName == "*") {
+ copyPublicSymbols(tempDst[lastName], dst);
+ } else if (importedName.match(/^\{.*\}$/)) {
+ importedName.slice(1,-1).split(',').forEach(function(sym) {
+ if (sym.match(/^.*=>.*$/)) {
+ copySymbol(moduleName, sym.split("=>")[0], tempDst[lastName], dst, sym.split("=>")[1]);
+ } else {
+ copySymbol(moduleName, sym, tempDst[lastName], dst);
+ }
+ });
+ } else {
+ copySymbol(moduleName, importedName, tempDst[lastName], dst);
+ }
+ }
+
+ //----------------------------------------------------------------
+ // scheduling
+ //----------------------------------------------------------------
+
+ var scheduledImports = [];
+
+ function scheduleImportPath(p, dst) {
+ scheduledImports.push([p, dst]);
+ }
+
+ function runScheduledImports() {
+ scheduledImports.forEach(function(x) {
+ importPath(x[0], x[1]);
+ });
+ }
+
+ //----------------------------------------------------------------
+ // The global import function
+ //----------------------------------------------------------------
+
+ _appjethidden_.importsAllowed = true;
+
+ globalScope['import'] = function(path1, path2, etc) {
+ if (!_appjethidden_.importsAllowed) {
+ throw Error("Imports are finished. No more imports are allowed.");
+ }
+
+ var dstScope = this;
+ if (arguments.length < 1) {
+ apiError("importModule() takes the name of at least one module as an argument.");
+ }
+ for (var i = 0; i < arguments.length; i++) {
+ var path = arguments[i];
+ debug("scheduling import: "+path);
+ scheduleImportPath(path, dstScope);
+ // evaluate all modules in this path.
+ var parts = path.split('.');
+ for (var j = 0; j < parts.length; j++) {
+ var moduleName = parts.slice(0,j+1).join('.');
+ loadModule(moduleName);
+ }
+ }
+ };
+
+ _appjethidden_.finishImports = function() {
+ debug("Running scheduled imports...");
+ runScheduledImports();
+ _appjethidden_.importsAllowed = false;
+ };
+
+ //----------------------------------------------------------------
+ // jimport
+ //----------------------------------------------------------------
+ function _jimportSinglePackage(pname, dstScope) {
+ //_appjethidden_._debugMessage("_jimportSinglePackage: "+pname);
+ // TODO: support "*" and "{}" syntax like scala.
+ var src = Packages;
+ var srcParent = null;
+ var localName = pname.split(".").pop();
+ var soFar = '';
+
+ pname.split(".").forEach(function(x) {
+ soFar += x+'.';
+ if (!src[x]) {
+ throw ('Could not find java package/class: '+soFar);
+ } else {
+ //_appjethidden_._debugMessage("descenting into "+src+"["+x+"]");
+ srcParent = src;
+ src = src[x];
+ }
+ });
+
+ if (String(src).indexOf('function') == 0) {
+ // TODO: checking String(src).indexOf('function') is rather brittle.
+ // is there a cleaner way?
+ // TODO: this only works on static functions... so make sure
+ // src[x] is a static function!
+ dstScope[localName] = function() {
+ return src.apply(srcParent, Array.prototype.slice.call(arguments));
+ };
+ } else {
+ // importing a regular java class
+ dstScope[localName] = src;
+ }
+ }
+
+ /**
+ * Import a java package over LiveConnect.
+ */
+ globalScope['jimport'] = function() {
+ var dstScope = this;
+ for (var i = 0; i < arguments.length; i++) {
+ var pname = arguments[i].split(".").pop();
+ _jimportSinglePackage(arguments[i], dstScope);
+ }
+ };
+
+ //----------------------------------------------------------------
+ // {appjet, request, response} imported by default
+ //----------------------------------------------------------------
+ globalScope['import'].call(globalScope,
+ "global.appjet.appjet", "global.request.request", "global.response.response");
+
+})(this);
+