aboutsummaryrefslogtreecommitdiffstats
path: root/infrastructure/framework-src
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2010-06-08 09:01:43 +0200
committerAlexander Sulfrian <alexander@sulfrian.net>2010-06-08 09:01:43 +0200
commitd1fa08fdc9cb11dccee76d668ff85df30458c295 (patch)
tree1d19df6405103577d872902486792e8c23bce711 /infrastructure/framework-src
parentd7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2 (diff)
parent70d1f9d6fcaefe611e778b8dbf3bafea8934aa08 (diff)
downloadetherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.tar.gz
etherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.tar.xz
etherpad-d1fa08fdc9cb11dccee76d668ff85df30458c295.zip
Merge remote branch 'upstream/master'
Conflicts: etherpad/src/etherpad/control/pro/admin/pro_admin_control.js etherpad/src/etherpad/control/pro/pro_main_control.js etherpad/src/etherpad/control/pro_help_control.js etherpad/src/etherpad/globals.js etherpad/src/etherpad/legacy_urls.js etherpad/src/etherpad/pne/pne_utils.js etherpad/src/etherpad/pro/pro_utils.js etherpad/src/main.js etherpad/src/plugins/fileUpload/templates/fileUpload.ejs etherpad/src/plugins/testplugin/templates/page.ejs etherpad/src/static/css/pad2_ejs.css etherpad/src/static/css/pro-help.css etherpad/src/static/img/jun09/pad/protop.gif etherpad/src/static/js/store.js etherpad/src/themes/default/templates/framed/framedheader-pro.ejs etherpad/src/themes/default/templates/main/home.ejs etherpad/src/themes/default/templates/pro-help/main.ejs etherpad/src/themes/default/templates/pro-help/pro-help-template.ejs infrastructure/com.etherpad/licensing.scala trunk/etherpad/src/etherpad/collab/ace/contentcollector.js trunk/etherpad/src/etherpad/collab/ace/linestylefilter.js trunk/etherpad/src/static/css/home-opensource.css trunk/etherpad/src/static/js/ace.js trunk/etherpad/src/static/js/linestylefilter_client.js trunk/etherpad/src/templates/email/eepnet_license_info.ejs trunk/etherpad/src/templates/pad/pad_body2.ejs trunk/etherpad/src/templates/pad/pad_content.ejs trunk/etherpad/src/templates/pad/padfull_body.ejs trunk/etherpad/src/templates/pro/admin/pne-license-manager.ejs
Diffstat (limited to '')
-rw-r--r--infrastructure/framework-src/modules/atomfeed.js (renamed from trunk/infrastructure/framework-src/modules/atomfeed.js)0
-rw-r--r--infrastructure/framework-src/modules/blob.js (renamed from trunk/infrastructure/framework-src/modules/blob.js)0
-rw-r--r--infrastructure/framework-src/modules/cache_utils.js (renamed from trunk/infrastructure/framework-src/modules/cache_utils.js)0
-rw-r--r--infrastructure/framework-src/modules/comet.js (renamed from trunk/infrastructure/framework-src/modules/comet.js)0
-rw-r--r--infrastructure/framework-src/modules/dateutils.js (renamed from trunk/infrastructure/framework-src/modules/dateutils.js)0
-rw-r--r--infrastructure/framework-src/modules/dispatch.js (renamed from trunk/infrastructure/framework-src/modules/dispatch.js)0
-rw-r--r--infrastructure/framework-src/modules/ejs.js477
-rw-r--r--infrastructure/framework-src/modules/email.js (renamed from trunk/infrastructure/framework-src/modules/email.js)0
-rw-r--r--infrastructure/framework-src/modules/exceptionutils.js (renamed from trunk/infrastructure/framework-src/modules/exceptionutils.js)0
-rw-r--r--infrastructure/framework-src/modules/execution.js61
-rw-r--r--infrastructure/framework-src/modules/fastJSON.js (renamed from trunk/infrastructure/framework-src/modules/fastJSON.js)0
-rw-r--r--infrastructure/framework-src/modules/faststatic.js342
-rw-r--r--infrastructure/framework-src/modules/fileutils.js (renamed from trunk/infrastructure/framework-src/modules/fileutils.js)0
-rw-r--r--infrastructure/framework-src/modules/funhtml.js (renamed from trunk/infrastructure/framework-src/modules/funhtml.js)0
-rw-r--r--infrastructure/framework-src/modules/global/appjet.js (renamed from trunk/infrastructure/framework-src/modules/global/appjet.js)0
-rw-r--r--infrastructure/framework-src/modules/global/request.js (renamed from trunk/infrastructure/framework-src/modules/global/request.js)0
-rw-r--r--infrastructure/framework-src/modules/global/response.js (renamed from trunk/infrastructure/framework-src/modules/global/response.js)0
-rw-r--r--infrastructure/framework-src/modules/image.js (renamed from trunk/infrastructure/framework-src/modules/image.js)0
-rw-r--r--infrastructure/framework-src/modules/jsutils.js (renamed from trunk/infrastructure/framework-src/modules/jsutils.js)0
-rw-r--r--infrastructure/framework-src/modules/netutils.js (renamed from trunk/infrastructure/framework-src/modules/netutils.js)0
-rw-r--r--infrastructure/framework-src/modules/process.js91
-rw-r--r--infrastructure/framework-src/modules/profiler.js (renamed from trunk/infrastructure/framework-src/modules/profiler.js)0
-rw-r--r--infrastructure/framework-src/modules/sessions.js (renamed from trunk/infrastructure/framework-src/modules/sessions.js)0
-rw-r--r--infrastructure/framework-src/modules/sqlbase/persistent_vars.js (renamed from trunk/infrastructure/framework-src/modules/sqlbase/persistent_vars.js)0
-rw-r--r--infrastructure/framework-src/modules/sqlbase/sqlbase.js (renamed from trunk/infrastructure/framework-src/modules/sqlbase/sqlbase.js)0
-rw-r--r--infrastructure/framework-src/modules/sqlbase/sqlcommon.js (renamed from trunk/infrastructure/framework-src/modules/sqlbase/sqlcommon.js)0
-rw-r--r--infrastructure/framework-src/modules/sqlbase/sqlobj.js551
-rw-r--r--infrastructure/framework-src/modules/stringutils.js (renamed from trunk/infrastructure/framework-src/modules/stringutils.js)0
-rw-r--r--infrastructure/framework-src/modules/sync.js (renamed from trunk/infrastructure/framework-src/modules/sync.js)0
-rw-r--r--infrastructure/framework-src/modules/timer.js (renamed from trunk/infrastructure/framework-src/modules/timer.js)0
-rw-r--r--infrastructure/framework-src/modules/varz.js (renamed from trunk/infrastructure/framework-src/modules/varz.js)0
-rw-r--r--infrastructure/framework-src/modules/yuicompressor.js (renamed from trunk/infrastructure/framework-src/modules/yuicompressor.js)0
-rw-r--r--infrastructure/framework-src/oncomet.js (renamed from trunk/infrastructure/framework-src/oncomet.js)0
-rw-r--r--infrastructure/framework-src/onerror.js (renamed from trunk/infrastructure/framework-src/onerror.js)0
-rw-r--r--infrastructure/framework-src/onprint.js (renamed from trunk/infrastructure/framework-src/onprint.js)0
-rw-r--r--infrastructure/framework-src/onrequest.js (renamed from trunk/infrastructure/framework-src/onrequest.js)0
-rw-r--r--infrastructure/framework-src/onreset.js (renamed from trunk/infrastructure/framework-src/onreset.js)0
-rw-r--r--infrastructure/framework-src/onsars.js (renamed from trunk/infrastructure/framework-src/onsars.js)0
-rw-r--r--infrastructure/framework-src/onscheduledtask.js (renamed from trunk/infrastructure/framework-src/onscheduledtask.js)0
-rw-r--r--infrastructure/framework-src/onshutdown.js (renamed from trunk/infrastructure/framework-src/onshutdown.js)0
-rw-r--r--infrastructure/framework-src/onstartup.js (renamed from trunk/infrastructure/framework-src/onstartup.js)0
-rw-r--r--infrastructure/framework-src/onsyntaxerror.js (renamed from trunk/infrastructure/framework-src/onsyntaxerror.js)0
-rw-r--r--infrastructure/framework-src/postamble.js (renamed from trunk/infrastructure/framework-src/postamble.js)0
-rw-r--r--infrastructure/framework-src/preamble.js (renamed from trunk/infrastructure/framework-src/preamble.js)0
-rw-r--r--infrastructure/framework-src/syntaxerror.js (renamed from trunk/infrastructure/framework-src/syntaxerror.js)0
45 files changed, 1522 insertions, 0 deletions
diff --git a/trunk/infrastructure/framework-src/modules/atomfeed.js b/infrastructure/framework-src/modules/atomfeed.js
index 4b86eeb..4b86eeb 100644
--- a/trunk/infrastructure/framework-src/modules/atomfeed.js
+++ b/infrastructure/framework-src/modules/atomfeed.js
diff --git a/trunk/infrastructure/framework-src/modules/blob.js b/infrastructure/framework-src/modules/blob.js
index af788a0..af788a0 100644
--- a/trunk/infrastructure/framework-src/modules/blob.js
+++ b/infrastructure/framework-src/modules/blob.js
diff --git a/trunk/infrastructure/framework-src/modules/cache_utils.js b/infrastructure/framework-src/modules/cache_utils.js
index f2a360c..f2a360c 100644
--- a/trunk/infrastructure/framework-src/modules/cache_utils.js
+++ b/infrastructure/framework-src/modules/cache_utils.js
diff --git a/trunk/infrastructure/framework-src/modules/comet.js b/infrastructure/framework-src/modules/comet.js
index 2331f8b..2331f8b 100644
--- a/trunk/infrastructure/framework-src/modules/comet.js
+++ b/infrastructure/framework-src/modules/comet.js
diff --git a/trunk/infrastructure/framework-src/modules/dateutils.js b/infrastructure/framework-src/modules/dateutils.js
index 72e87c8..72e87c8 100644
--- a/trunk/infrastructure/framework-src/modules/dateutils.js
+++ b/infrastructure/framework-src/modules/dateutils.js
diff --git a/trunk/infrastructure/framework-src/modules/dispatch.js b/infrastructure/framework-src/modules/dispatch.js
index e7e3ef0..e7e3ef0 100644
--- a/trunk/infrastructure/framework-src/modules/dispatch.js
+++ b/infrastructure/framework-src/modules/dispatch.js
diff --git a/infrastructure/framework-src/modules/ejs.js b/infrastructure/framework-src/modules/ejs.js
new file mode 100644
index 0000000..58c67bc
--- /dev/null
+++ b/infrastructure/framework-src/modules/ejs.js
@@ -0,0 +1,477 @@
+/*--------------------------------------------------------------------------
+ * EJS - Embedded JavaScript, version 0.1.0
+ * Copyright (c) 2007 Edward Benson
+ * http://www.edwardbenson.com/projects/ejs
+ * ------------------------------------------------------------------------
+ *
+ * EJS is freely distributable under the terms of an MIT-style license.
+ *
+ * EJS is a client-side preprocessing engine written in and for JavaScript.
+ * If you have used PHP, ASP, JSP, or ERB then you get the idea: code embedded
+ * in <% // Code here %> tags will be executed, and code embedded in <%= .. %>
+ * tags will be evaluated and appended to the output.
+ *
+ * This is essentially a direct JavaScript port of Masatoshi Seki's erb.rb
+ * from the Ruby Core, though it contains a subset of ERB's functionality.
+ *
+ * Requirements:
+ * prototype.js
+ *
+ * Usage:
+ * // source should be either a string or a DOM node whose innerHTML
+ * // contains EJB source.
+ * var source = "<% var ejb="EJB"; %><h1>Hello, <%= ejb %>!</h1>";
+ * var compiler = new EjsCompiler(source);
+ * compiler.compile();
+ * var output = eval(compiler.out);
+ * alert(output); // -> "<h1>Hello, EJB!</h1>"
+ *
+ * For a demo: see demo.html
+ * For the license: see license.txt
+ *
+ *--------------------------------------------------------------------------*/
+
+import("jsutils.*");
+import("funhtml");
+import("etherpad.log");
+
+jimport("java.lang.System.out.println");
+jimport("net.appjet.ajstdlib.execution.executeCodeInNewScope");
+
+/* Make a split function like Ruby's: "abc".split(/b/) -> ['a', 'b', 'c'] */
+function rsplit(x, regex) {
+ var item = x;
+ var result = regex.exec(item);
+ var retArr = new Array();
+ while (result != null)
+ {
+ var first_idx = result.index;
+ var last_idx = regex.lastIndex;
+ if ((first_idx) != 0)
+ {
+ var first_bit = item.substring(0,first_idx);
+ retArr.push(item.substring(0,first_idx));
+ item = item.slice(first_idx);
+ }
+ retArr.push(result[0]);
+ item = item.slice(result[0].length);
+ result = regex.exec(item);
+ }
+ if (! item == '')
+ {
+ retArr.push(item);
+ }
+ return retArr;
+};
+
+/* Chop is nice to have too */
+function chop(x) {
+ return x.substr(0, x.length - 1);
+}
+
+/* Adaptation from the Scanner of erb.rb */
+var EjsScanner = function(source, left, right) {
+ this.left_delimiter = left +'%'; //<%
+ this.right_delimiter = '%'+right; //>
+ this.double_left = left+'%%';
+ this.double_right = '%%'+right;
+ this.left_equal = left+'%=';
+ this.left_colon = left+'%:';
+ this.left_comment = left+'%#';
+ if(left=='[') {
+ this.SplitRegexp = /(\[%%)|(%%\])|(\[%:)|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
+ }
+ else {
+ this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_colon+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)')
+ }
+
+ this.source = source;
+ this.stag = null;
+ this.lines = 0;
+};
+EjsView = function(data) {
+ this.data = data;
+};
+EjsView.prototype.partial = function(options, data){
+ if(!data) data = this.data;
+ return new EJS(options).render(data);
+};
+
+EjsScanner.to_text = function(input){
+ if(input == null || input === undefined)
+ return '';
+ if(input instanceof Date)
+ return input.toDateString();
+ if(input.toString)
+ return input.toString();
+ return '';
+}
+
+EjsScanner.prototype = {
+
+ /* For each line, scan! */
+ scan: function(block) {
+ scanline = this.scanline;
+ regex = this.SplitRegexp;
+ if (! this.source == '')
+ {
+ var source_split = rsplit(this.source, /\n/);
+ for(var i=0; i<source_split.length; i++) {
+ var item = source_split[i];
+ this.scanline(item, regex, block);
+ }
+ }
+ },
+
+ /* For each token, block! */
+ scanline: function(line, regex, block) {
+ this.lines++;
+ var line_split = rsplit(line, regex);
+ for(var i=0; i<line_split.length; i++) {
+ var token = line_split[i];
+ if (token != null) {
+ try{
+ block(token, this);
+ }catch(e){
+ throw {type: 'EjsScanner', line: this.lines};
+ }
+ }
+ }
+ }
+};
+
+/* Adaptation from the Buffer of erb.rb */
+var EjsBuffer = function(pre_cmd, post_cmd) {
+ this.line = new Array();
+ this.script = "";
+ this.pre_cmd = pre_cmd;
+ this.post_cmd = post_cmd;
+
+ for (var i=0; i<this.pre_cmd.length; i++)
+ {
+ this.push(pre_cmd[i]);
+ }
+}
+EjsBuffer.prototype = {
+
+ push: function(cmd) {
+ this.line.push(cmd);
+ },
+
+ cr: function() {
+ this.script = this.script + this.line.join('; ');
+ this.line = new Array();
+ this.script = this.script + "\n";
+ },
+
+ close: function() {
+ if (this.line.length > 0)
+ {
+ for (var i=0; i<this.post_cmd.length; i++)
+ {
+ this.push(pre_cmd[i]);
+ }
+ this.script = this.script + this.line.join('; ');
+ line = null;
+ }
+ }
+
+};
+
+/* Adaptation from the Compiler of erb.rb */
+EjsCompiler = function(source, left) {
+ this.pre_cmd = ['var ejs_data = "";'];
+ this.post_cmd = new Array();
+ this.source = ' ';
+ if (source != null)
+ {
+ if (typeof source == 'string')
+ {
+ source = source.replace(/\r\n/g, "\n");
+ source = source.replace(/\r/g, "\n");
+ this.source = source;
+ }
+ else if (source.innerHTML)
+ {
+ this.source = source.innerHTML;
+ }
+ if (typeof this.source != 'string')
+ {
+ this.source = "";
+ }
+ }
+ left = left || '<'
+ var right = '>'
+ switch(left) {
+ case '[':
+ right = ']'
+ break;
+ case '<':
+ break;
+ default:
+ throw left+' is not a supported deliminator'
+ break;
+ }
+ this.scanner = new EjsScanner(this.source, left, right);
+ this.out = '';
+}
+EjsCompiler.prototype = {
+ compile: function(options) {
+ options = options || {};
+ this.out = '';
+ var put_cmd = "ejs_data += ";
+ var insert_cmd = put_cmd;
+ var buff = new EjsBuffer(this.pre_cmd, this.post_cmd);
+ var content = '';
+ var clean = function(content)
+ {
+ content = content.replace(/\\/g, '\\\\');
+ content = content.replace(/\n/g, '\\n');
+ content = content.replace(/\"/g, '\\"');
+ return content;
+ };
+ this.scanner.scan(function(token, scanner) {
+ if (scanner.stag == null)
+ {
+ //alert(token+'|'+(token == "\n"))
+ switch(token) {
+ case '\n':
+ content = content + "\n";
+ buff.push(put_cmd + '"' + clean(content) + '";');
+ buff.cr();
+ content = '';
+ break;
+ case scanner.left_delimiter:
+ case scanner.left_equal:
+ case scanner.left_colon:
+ case scanner.left_comment:
+ scanner.stag = token;
+ if (content.length > 0)
+ {
+ // Chould be content.dump in Ruby
+
+ buff.push(put_cmd + '"' + clean(content) + '"');
+ }
+ content = '';
+ break;
+ case scanner.double_left:
+ content = content + scanner.left_delimiter;
+ break;
+ default:
+ content = content + token;
+ break;
+ }
+ }
+ else {
+ switch(token) {
+ case scanner.right_delimiter:
+ switch(scanner.stag) {
+ case scanner.left_delimiter:
+ if (content[content.length - 1] == '\n')
+ {
+ content = chop(content);
+ buff.push(content);
+ buff.cr();
+ }
+ else {
+ buff.push(content);
+ }
+ break;
+ case scanner.left_equal:
+ buff.push(insert_cmd + "(EjsScanner.to_text(" + content + "))");
+ break;
+ case scanner.left_colon:
+ buff.push(insert_cmd + content);
+ break;
+ }
+ scanner.stag = null;
+ content = '';
+ break;
+ case scanner.double_right:
+ content = content + scanner.right_delimiter;
+ break;
+ default:
+ content = content + token;
+ break;
+ }
+ }
+ });
+ if (content.length > 0)
+ {
+ // Chould be content.dump in Ruby
+ buff.push(put_cmd + '"' + clean(content) + '"');
+ }
+ buff.close();
+ this.out = buff.script + ";";
+ var to_be_evaled = [
+ 'var process = function(_CONTEXT,_VIEW) {',
+ ' with(_VIEW) {',
+ ' with (_CONTEXT) {',
+ this.out,
+ ' return ejs_data;',
+ ' }',
+ ' }',
+ '};'
+ ].join('');
+ // make funhtml.* available in parent scope.
+ var parentScope = {};
+ parentScope.EjsScanner = EjsScanner;
+ keys(funhtml).forEach(function(k) {
+ parentScope[k] = funhtml[k];
+ });
+ var ret = executeCodeInNewScope(
+ parentScope,
+ to_be_evaled,
+ (options.name || "template"),
+ 1
+ );
+ this.process = ret.process;
+ }
+}
+
+
+//type, cache, folder
+EJS = function( options ){
+ this.set_options(options);
+
+ if(options.url){
+ var template = EJS.get(options.url, this.cache);
+ if (template) return template;
+ if (template == EJS.INVALID_PATH) return null;
+ this.text = EJS.request(options.url);
+ if(this.text == null){
+ //EJS.update(options.url, this.INVALID_PATH);
+ throw 'There is no template at '+options.url;
+ }
+ this.name = options.url;
+ }else if(options.element)
+ {
+ if(typeof options.element == 'string'){
+ var name = options.element;
+ options.element = document.getElementById( options.element );
+ if(options.element == null) throw name+'does not exist!';
+ }
+ if(options.element.value){
+ this.text = options.element.value;
+ }else{
+ this.text = options.element.innerHTML;
+ }
+ this.name = options.element.id;
+ this.type = '[';
+ }
+ var template = new EjsCompiler(this.text, this.type);
+
+ template.compile(options);
+
+
+ EJS.update(this.name, this);
+ this.template = template;
+};
+EJS.config = function(options){
+ EJS.cache = options.cache != null ? options.cache : EJS.cache;
+ EJS.type = options.type != null ? options.type : EJS.type;
+ var templates_directory = {}; //nice and private container
+
+ EJS.get = function(path, cache){
+ if(cache == false) return null;
+ if(templates_directory[path]) return templates_directory[path];
+ return null;
+ };
+
+ EJS.update = function(path, template) {
+ if(path == null) return;
+ templates_directory[path] = template;
+ };
+
+ EJS.INVALID_PATH = -1;
+
+
+};
+EJS.config( {cache: true, type: '<' } );
+
+EJS.prototype = {
+ render : function(object){
+ var v = new EjsView(object);
+ return this.template.process.call(v, object, v);
+ },
+ out : function(){
+ return this.template.out;
+ },
+ set_options : function(options){
+ this.type = options.type != null ? options.type : EJS.type;
+ this.cache = options.cache != null ? options.cache : EJS.cache;
+ this.text = options.text != null ? options.text : null;
+ this.name = options.name != null ? options.name : null;
+ },
+ // called without options, returns a function that takes the object
+ // called with options being a string, uses that as a url
+ // called with options as an object
+ update : function(element, options){
+ if(typeof element == 'string'){
+ element = document.getElementById(element);
+ }
+ if(options == null){
+ _template = this;
+ return function(object){
+ EJS.prototype.update.call(_template, element, object);
+ };
+ }
+ if(typeof options == 'string'){
+ params = {};
+ params.url = options;
+ _template = this;
+ params.onComplete = function(request){
+ var object = eval( request.responseText );
+ EJS.prototype.update.call(_template, element, object);
+ };
+ EJS.ajax_request(params);
+ }else
+ {
+ element.innerHTML = this.render(options);
+ }
+ }
+};
+
+ EJS.newRequest = function(){
+ var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
+ for(var i = 0; i < factories.length; i++) {
+ try {
+ var request = factories[i]();
+ if (request != null) return request;
+ }
+ catch(e) { continue;}
+ }
+ };
+
+ EJS.request = function(path){
+ var request = new EJS.newRequest();
+ request.open("GET", path, false);
+
+ try{request.send(null);}
+ catch(e){return null;}
+
+ if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
+
+ return request.responseText
+ };
+ EJS.ajax_request = function(params){
+ params.method = ( params.method ? params.method : 'GET');
+
+ var request = new EJS.newRequest();
+ request.onreadystatechange = function(){
+ if(request.readyState == 4){
+ if(request.status == 200){
+ params.onComplete(request);
+ }else
+ {
+ params.onComplete(request);
+ }
+ }
+ };
+ request.open(params.method, params.url);
+ request.send(null);
+ };
+
+//}
+
+
diff --git a/trunk/infrastructure/framework-src/modules/email.js b/infrastructure/framework-src/modules/email.js
index 2d81dc3..2d81dc3 100644
--- a/trunk/infrastructure/framework-src/modules/email.js
+++ b/infrastructure/framework-src/modules/email.js
diff --git a/trunk/infrastructure/framework-src/modules/exceptionutils.js b/infrastructure/framework-src/modules/exceptionutils.js
index b572a3a..b572a3a 100644
--- a/trunk/infrastructure/framework-src/modules/exceptionutils.js
+++ b/infrastructure/framework-src/modules/exceptionutils.js
diff --git a/infrastructure/framework-src/modules/execution.js b/infrastructure/framework-src/modules/execution.js
new file mode 100644
index 0000000..2f9d933
--- /dev/null
+++ b/infrastructure/framework-src/modules/execution.js
@@ -0,0 +1,61 @@
+/**
+ * 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.
+ */
+
+import("jsutils.{scalaF0,scalaF1}");
+
+/**
+ * Asynchronously call a function as soon as the current request completes.
+ **/
+function async(f) {
+ Packages.net.appjet.ajstdlib.execution.runAsync(appjet.context, f);
+}
+
+function initTaskThreadPool(name, poolSize) {
+ Packages.net.appjet.ajstdlib.execution.createNamedTaskThreadPool(name, poolSize);
+}
+
+function scheduleTask(poolName, taskName, delayMillis, args) {
+ return Packages.net.appjet.ajstdlib.execution.scheduleTaskInPool(poolName, taskName, delayMillis, args);
+}
+
+function shutdownAndWaitOnTaskThreadPool(poolName, timeoutMillis) {
+ return Packages.net.appjet.ajstdlib.execution.shutdownAndWaitOnTaskThreadPool(poolName, timeoutMillis);
+}
+
+function fancyAssEval(initCode, mainCode) {
+ function init(runner) {
+ Packages.net.appjet.bodylock.BodyLock.evaluateString(
+ runner.globalScope(),
+ initCode,
+ "eval'd code imports",
+ 1);
+ }
+ var runner = Packages.net.appjet.oui.ScopeReuseManager.getEmpty(scalaF1(init));
+ var requestWrapper = null;
+ if (request.underlying !== undefined)
+ requestWrapper = new Packages.net.appjet.oui.RequestWrapper(request.underlying);
+ var ec = new Packages.net.appjet.oui.ExecutionContext(
+ requestWrapper,
+ null, runner);
+ return Packages.net.appjet.oui.ExecutionContextUtils.withContext(ec,
+ scalaF0(function() {
+ return Packages.net.appjet.bodylock.BodyLock.evaluateString(
+ runner.globalScope(),
+ mainCode,
+ "eval'd code main",
+ 1);
+ }));
+} \ No newline at end of file
diff --git a/trunk/infrastructure/framework-src/modules/fastJSON.js b/infrastructure/framework-src/modules/fastJSON.js
index 3198b96..3198b96 100644
--- a/trunk/infrastructure/framework-src/modules/fastJSON.js
+++ b/infrastructure/framework-src/modules/fastJSON.js
diff --git a/infrastructure/framework-src/modules/faststatic.js b/infrastructure/framework-src/modules/faststatic.js
new file mode 100644
index 0000000..920be8c
--- /dev/null
+++ b/infrastructure/framework-src/modules/faststatic.js
@@ -0,0 +1,342 @@
+/**
+ * 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.
+ */
+
+/**
+ * @fileOverview serving static files, including js and css, and cacheing
+ * and minifying.
+ *
+ * Terminology Note:
+ * "path" is confusing because paths can be part of URLs and part
+ * of filesystem paths, and static files have both types of paths
+ * associated with them. Therefore, in this module:
+ *
+ * LOCALDIR or LOCALFILE refers to directories or files on the filesystem.
+ *
+ * HREF is used to describe things that go in a URL.
+ */
+
+import("fileutils.{readFile,readFileBytes}");
+import("yuicompressor");
+import("stringutils");
+import("varz");
+import("ejs.EJS");
+
+jimport("java.lang.System.out.println");
+
+//----------------------------------------------------------------
+// Content Type Guessing
+//----------------------------------------------------------------
+
+var _contentTypes = {
+ 'gif': 'image/gif',
+ 'png': 'image/png',
+ 'jpg': 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'css': 'text/css',
+ 'js': 'application/x-javascript',
+ 'txt': 'text/plain',
+ 'html': 'text/html; charset=utf-8',
+ 'ico': 'image/x-icon',
+ 'swf': 'application/x-shockwave-flash',
+ 'zip': 'application/zip',
+ 'xml': 'application/xml'
+};
+
+var _gzipableTypes = {
+ 'text/css': true,
+ 'application/x-javascript': true,
+ 'text/html; charset=utf-8': true
+};
+
+function _guessContentType(path) {
+ var ext = path.split('.').pop().toLowerCase();
+ return _contentTypes[ext] || 'text/plain';
+}
+
+//----------------------------------------------------------------
+
+function _getCache(name) {
+ var m = 'faststatic';
+ if (!appjet.cache[m]) {
+ appjet.cache[m] = {};
+ }
+ var c = appjet.cache[m];
+ if (!c[name]) {
+ c[name] = {};
+ }
+ return c[name];
+}
+
+var _mtimeCheckInterval = 5000; // 5 seconds
+
+function _getMTime(f) {
+ var mcache = _getCache('mtimes');
+ var now = +(new Date);
+ if (appjet.config.devMode ||
+ !(mcache[f] && (now - mcache[f].lastCheck < _mtimeCheckInterval))) {
+ var jfile = new net.appjet.oui.JarVirtualFile(f);
+ if (jfile.exists() && !jfile.isDirectory()) {
+ mcache[f] = {
+ lastCheck: now,
+ mtime: jfile.lastModified()
+ };
+ } else {
+ mcache[f] = null;
+ }
+ }
+ if (mcache[f]) {
+ return +mcache[f].mtime;
+ } else {
+ return null;
+ }
+}
+
+function manglePluginPath(localFile, fileType) {
+ var prefix = '/static/' + fileType + '/plugins/';
+ if (localFile.substring(0, prefix.length) != prefix)
+ return localFile;
+ var suffix = localFile.substring(prefix.length);
+ var plugin = suffix.split('/', 1)[0];
+ suffix = suffix.substring(plugin.length + 1);
+ return '/plugins/' + plugin + '/static/' + fileType + '/' + suffix;
+}
+
+function manglePluginPaths(localFile) {
+ return manglePluginPath(
+ manglePluginPath(
+ manglePluginPath(
+ manglePluginPath(
+ manglePluginPath(
+ localFile,
+ 'js'),
+ 'css'),
+ 'swf'),
+ 'html'),
+ 'zip');
+}
+
+function _wrapFile(localFile) {
+ return {
+ getPath: function() { return localFile; },
+ getMTime: function() { return _getMTime(localFile); },
+ getContents: function() { return _readFileAndProcess(manglePluginPaths(localFile), 'string'); }
+ };
+}
+
+function _readFileAndProcess(fileName, type) {
+ if (fileName.slice(-8) == "_ejs.css") {
+ // run CSS through EJS
+ var template = readFile(fileName);
+ var ejs = new EJS({text:template, name:fileName});
+ var resultString = ejs.render({});
+ if (type == 'bytes') {
+ return new java.lang.String(resultString).getBytes("UTF-8");
+ }
+ else {
+ return resultString;
+ }
+ }
+ else if (type == 'string') {
+ return readFile(fileName);
+ }
+ else if (type == 'bytes') {
+ return readFileBytes(fileName);
+ }
+}
+
+function _cachedFileBytes(f) {
+ var mtime = _getMTime(f);
+ if (!mtime) { return null; }
+ var fcache = _getCache('file-bytes-cache');
+ if (!(fcache[f] && (fcache[f].mtime == mtime))) {
+ varz.incrementInt("faststatic-file-bytes-cache-miss");
+ var bytes = _readFileAndProcess(f, 'bytes');
+ if (bytes) {
+ fcache[f] = {mtime: mtime, bytes: bytes};
+ };
+ }
+ if (fcache[f] && fcache[f].bytes) {
+ return fcache[f].bytes;
+ } else {
+ return null;
+ }
+}
+
+function _shouldGzip(contentType) {
+ var userAgent = request.headers["User-Agent"];
+ if (! userAgent) return false;
+ if (! (/Firefox/.test(userAgent) || /webkit/i.test(userAgent))) return false;
+ if (! _gzipableTypes[contentType]) return false;
+
+ return request.acceptsGzip;
+}
+
+function _getCachedGzip(original, key) {
+ var c = _getCache("gzipped");
+ if (! c[key] || ! java.util.Arrays.equals(c[key].original, original)) {
+ c[key] = {original: original,
+ gzip: stringutils.gzip(original)};
+ }
+ return c[key].gzip;
+}
+
+function _setGzipHeader() {
+ response.setHeader("Content-Encoding", "gzip");
+}
+
+//----------------------------------------------------------------
+
+/**
+ * Function for serving a single static file.
+ */
+function singleFileServer(localPath, opts) {
+ var contentType = _guessContentType(localPath);
+
+ return function() {
+ (opts.cache ? response.alwaysCache() : response.neverCache());
+ response.setContentType(contentType);
+ var bytes = _cachedFileBytes(localPath);
+ if (bytes) {
+ if (_shouldGzip(contentType)) {
+ bytes = _getCachedGzip(bytes, "file:"+localPath);
+ _setGzipHeader();
+ }
+ response.writeBytes(bytes);
+ return true;
+ } else {
+ return false;
+ }
+ };
+}
+
+/**
+ * valid opts:
+ * alwaysCache: default false
+ */
+function directoryServer(localDir, opts) {
+ if (stringutils.endsWith(localDir, "/")) {
+ localDir = localDir.substr(0, localDir.length-1);
+ }
+ return function(relpath) {
+ if (stringutils.startsWith(relpath, "/")) {
+ relpath = relpath.substr(1);
+ }
+ if (relpath.indexOf('..') != -1) {
+ response.forbid();
+ }
+ (opts.cache ? response.alwaysCache() : response.neverCache());
+ var contentType = _guessContentType(relpath);
+ response.setContentType(contentType);
+ var fullPath = localDir + "/" + relpath;
+ var bytes = _cachedFileBytes(fullPath);
+
+ if (bytes) {
+ if (_shouldGzip(contentType)) {
+ bytes = _getCachedGzip(bytes, "file:"+fullPath);
+ _setGzipHeader();
+ }
+ response.writeBytes(bytes);
+ return true;
+ } else {
+ return false;
+ }
+ };
+}
+
+/**
+ * Serves cat files, which are concatenated versions of many files.
+ */
+function compressedFileServer(opts) {
+ var cfcache = _getCache('compressed-files');
+ return function() {
+ var key = request.path.split('/').slice(-1)[0];
+ var contentType = _guessContentType(request.path);
+ response.setContentType(contentType);
+ response.alwaysCache();
+ var data = cfcache[key];
+ if (data) {
+ if (_shouldGzip(contentType)) {
+ data = _getCachedGzip((new java.lang.String(data)).getBytes(response.getCharacterEncoding()), "comp:"+key);
+ _setGzipHeader();
+ response.writeBytes(data);
+ } else {
+ response.write(data);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ };
+}
+
+function getCompressedFilesKey(type, baseLocalDir, localFileList) {
+ if (stringutils.endsWith(baseLocalDir, '/')) {
+ baseLocalDir = baseLocalDir.substr(0, baseLocalDir.length-1);
+ }
+
+ var fileList = [];
+ // convert passed-in file list into list of our file objects
+ localFileList.forEach(function(f) {
+ if (typeof(f) == 'string') {
+ fileList.push(_wrapFile(baseLocalDir+'/'+f));
+ } else {
+ fileList.push(f);
+ }
+ });
+
+ // have we seen this exact fileset before?
+ var fsId = fileList.map(function(f) { return f.getPath(); }).join('|');
+ var fsMTime = Math.max.apply(this,
+ fileList.map(function(f) { return f.getMTime(); }));
+
+ var kdcache = _getCache('fileset-keydata-cache');
+ if (!(kdcache[fsId] && (kdcache[fsId].mtime == fsMTime))) {
+ //println("cache miss for fileset: "+fsId);
+ //println("compressing fileset...");
+ kdcache[fsId] = {
+ mtime: fsMTime,
+ keyString: _compressFilesAndMakeKey(type, fileList)
+ };
+ }
+ return kdcache[fsId].keyString;
+}
+
+function _compressFilesAndMakeKey(type, fileList) {
+ function _compress(s) {
+ if (type == 'css') {
+ varz.incrementInt("faststatic-yuicompressor-compressCSS");
+ return yuicompressor.compressCSS(s);
+ } else if (type == 'js') {
+ varz.incrementInt("faststatic-yuicompressor-compressJS");
+ return yuicompressor.compressJS(s);
+ } else {
+ throw Error('Dont know how to compress this filetype: '+type);
+ }
+ }
+
+ var fullstr = "";
+ fileList.forEach(function(f) {
+ fullstr += _compress(f.getContents());
+ });
+
+ fullstr = _compress(fullstr);
+
+ var key = stringutils.md5(fullstr) + '.' + type;
+ var cfcache = _getCache('compressed-files');
+ cfcache[key] = fullstr;
+ return key;
+}
+
diff --git a/trunk/infrastructure/framework-src/modules/fileutils.js b/infrastructure/framework-src/modules/fileutils.js
index aaf12e2..aaf12e2 100644
--- a/trunk/infrastructure/framework-src/modules/fileutils.js
+++ b/infrastructure/framework-src/modules/fileutils.js
diff --git a/trunk/infrastructure/framework-src/modules/funhtml.js b/infrastructure/framework-src/modules/funhtml.js
index c27b667..c27b667 100644
--- a/trunk/infrastructure/framework-src/modules/funhtml.js
+++ b/infrastructure/framework-src/modules/funhtml.js
diff --git a/trunk/infrastructure/framework-src/modules/global/appjet.js b/infrastructure/framework-src/modules/global/appjet.js
index 135ac44..135ac44 100644
--- a/trunk/infrastructure/framework-src/modules/global/appjet.js
+++ b/infrastructure/framework-src/modules/global/appjet.js
diff --git a/trunk/infrastructure/framework-src/modules/global/request.js b/infrastructure/framework-src/modules/global/request.js
index a4327f9..a4327f9 100644
--- a/trunk/infrastructure/framework-src/modules/global/request.js
+++ b/infrastructure/framework-src/modules/global/request.js
diff --git a/trunk/infrastructure/framework-src/modules/global/response.js b/infrastructure/framework-src/modules/global/response.js
index 7236920..7236920 100644
--- a/trunk/infrastructure/framework-src/modules/global/response.js
+++ b/infrastructure/framework-src/modules/global/response.js
diff --git a/trunk/infrastructure/framework-src/modules/image.js b/infrastructure/framework-src/modules/image.js
index 8aec74b..8aec74b 100644
--- a/trunk/infrastructure/framework-src/modules/image.js
+++ b/infrastructure/framework-src/modules/image.js
diff --git a/trunk/infrastructure/framework-src/modules/jsutils.js b/infrastructure/framework-src/modules/jsutils.js
index 02f81a2..02f81a2 100644
--- a/trunk/infrastructure/framework-src/modules/jsutils.js
+++ b/infrastructure/framework-src/modules/jsutils.js
diff --git a/trunk/infrastructure/framework-src/modules/netutils.js b/infrastructure/framework-src/modules/netutils.js
index 6616b76..6616b76 100644
--- a/trunk/infrastructure/framework-src/modules/netutils.js
+++ b/infrastructure/framework-src/modules/netutils.js
diff --git a/infrastructure/framework-src/modules/process.js b/infrastructure/framework-src/modules/process.js
new file mode 100644
index 0000000..48ab62e
--- /dev/null
+++ b/infrastructure/framework-src/modules/process.js
@@ -0,0 +1,91 @@
+/**
+ * Simple way to execute external commands through javascript
+ *
+ * @example
+ cmd = exec("cat");
+ System.out.println("First: " +cmd.write("this is a loop.").read(Process.READ_AVAILABLE)); // prints "this is a loop."
+ System.out.println("Second: " +cmd.writeAndClose(" hi there").result()); // prints "this is a loop. hi there"
+ *
+ */
+
+jimport("java.lang.Runtime");
+jimport("java.io.BufferedInputStream");
+jimport("java.io.BufferedOutputStream");
+jimport("java.lang.System");
+
+/* returns a process */
+function exec(process) {
+ return new Process(process);
+};
+
+function Process(cmd) {
+ this.cmd = cmd;
+ this.proc = Runtime.getRuntime().exec(cmd);
+ this.resultText = "";
+ this.inputStream = new BufferedInputStream(this.proc.getInputStream());
+ this.errorStream = new BufferedInputStream(this.proc.getErrorStream());
+ this.outputStream = new BufferedOutputStream(this.proc.getOutputStream());
+}
+
+Process.CHUNK_SIZE = 1024;
+Process.READ_ALL = -1;
+Process.READ_AVAILABLE = -2;
+
+Process.prototype.write = function(stdinText) {
+ this.outputStream.write(new java.lang.String(stdinText).getBytes());
+ this.outputStream.flush();
+ return this;
+};
+
+Process.prototype.writeAndClose = function(stdinText) {
+ this.write(stdinText);
+ this.outputStream.close();
+ return this;
+};
+
+/* Python file-like behavior: read specified number of bytes, else until EOF*/
+Process.prototype.read = function(nbytesToRead, stream) {
+ var inputStream = stream || this.inputStream;
+ var availBytes = inputStream.available();
+ if (!availBytes) return null;
+
+ var result = "";
+ var nbytes = nbytesToRead || Process.READ_ALL;
+ var readAll = (nbytes == Process.READ_ALL);
+ var readAvailable = (nbytes == Process.READ_AVAILABLE);
+ while (nbytes > 0 || readAll || readAvailable) {
+ var chunkSize = readAll ? Process.CHUNK_SIZE :
+ readAvailable ? Process.CHUNK_SIZE : nbytes;
+
+ // allocate a java byte array
+ var bytes = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, chunkSize);
+
+ var len = inputStream.read(bytes, 0, chunkSize);
+
+ // at end of stream, or when we run out of data, stop reading in chunks.
+ if (len == -1) break;
+ if (nbytes > 0) nbytes -= len;
+
+ result += new java.lang.String(bytes);
+
+ if (readAvailable && inputStream.available() == 0) break;
+ }
+
+ this.resultText += new String(result);
+ return new String(result);
+};
+
+Process.prototype.result = function() {
+ this.outputStream.close();
+ this.proc.waitFor();
+ this.read(Process.READ_ALL, this.inputStream);
+ return new String(this.resultText);
+};
+
+Process.prototype.resultOrError = function() {
+ this.proc.waitFor();
+ this.read(Process.READ_ALL, this.inputStream);
+ var result = this.resultText;
+ if(!result || result == "") result = this.read(Process.READ_ALL, this.errorStream);
+ return result || "";
+};
diff --git a/trunk/infrastructure/framework-src/modules/profiler.js b/infrastructure/framework-src/modules/profiler.js
index 223c197..223c197 100644
--- a/trunk/infrastructure/framework-src/modules/profiler.js
+++ b/infrastructure/framework-src/modules/profiler.js
diff --git a/trunk/infrastructure/framework-src/modules/sessions.js b/infrastructure/framework-src/modules/sessions.js
index 3d0041b..3d0041b 100644
--- a/trunk/infrastructure/framework-src/modules/sessions.js
+++ b/infrastructure/framework-src/modules/sessions.js
diff --git a/trunk/infrastructure/framework-src/modules/sqlbase/persistent_vars.js b/infrastructure/framework-src/modules/sqlbase/persistent_vars.js
index 1c4cc95..1c4cc95 100644
--- a/trunk/infrastructure/framework-src/modules/sqlbase/persistent_vars.js
+++ b/infrastructure/framework-src/modules/sqlbase/persistent_vars.js
diff --git a/trunk/infrastructure/framework-src/modules/sqlbase/sqlbase.js b/infrastructure/framework-src/modules/sqlbase/sqlbase.js
index 3df1a0f..3df1a0f 100644
--- a/trunk/infrastructure/framework-src/modules/sqlbase/sqlbase.js
+++ b/infrastructure/framework-src/modules/sqlbase/sqlbase.js
diff --git a/trunk/infrastructure/framework-src/modules/sqlbase/sqlcommon.js b/infrastructure/framework-src/modules/sqlbase/sqlcommon.js
index 360f5e2..360f5e2 100644
--- a/trunk/infrastructure/framework-src/modules/sqlbase/sqlcommon.js
+++ b/infrastructure/framework-src/modules/sqlbase/sqlcommon.js
diff --git a/infrastructure/framework-src/modules/sqlbase/sqlobj.js b/infrastructure/framework-src/modules/sqlbase/sqlobj.js
new file mode 100644
index 0000000..e599c92
--- /dev/null
+++ b/infrastructure/framework-src/modules/sqlbase/sqlobj.js
@@ -0,0 +1,551 @@
+/**
+ * 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.
+ */
+
+import("cache_utils.syncedWithCache");
+import("sqlbase.sqlcommon.*");
+import("jsutils.*");
+import("etherpad.log");
+
+jimport("java.lang.System.out.println");
+jimport("java.sql.Statement");
+
+function _withCache(name, fn) {
+ return syncedWithCache('sqlobj.'+name, fn);
+}
+
+function getIdColspec() {
+ return ('INT NOT NULL '+autoIncrementClause()+' PRIMARY KEY');
+}
+
+function getLongtextColspec(extra) {
+ var spec = getSqlBase().longTextType();
+ if (extra) {
+ spec = (spec + " " + extra);
+ }
+ return spec;
+}
+
+function getBoolColspec(extra) {
+ var spec;
+ if (isMysql()) {
+ spec = 'TINYINT(1)';
+ } else {
+ spec = 'SMALLINT';
+ }
+ if (extra) {
+ spec = (spec + " " + extra);
+ }
+ return spec;
+}
+
+function getDateColspec(extra) {
+ var spec;
+ if (isMysql()) {
+ spec = 'DATETIME';
+ } else {
+ spec = 'TIMESTAMP';
+ }
+ if (extra) {
+ spec = (spec + " " + extra);
+ }
+ return spec;
+}
+
+function _bq(x) { return btquote(x); }
+
+/*
+ * for debugging queries
+ */
+function _qdebug(q) {
+ if (appjet.config.debugSQL) {
+ println(q);
+ }
+}
+
+/** executeFn is either "execute" or "executeUpdate" "executeQuery" */
+function _execute(stmnt, executeFn) {
+ if (!executeFn) {
+ executeFn = 'execute';
+ }
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ return closing(pstmnt, function() {
+ _qdebug(stmnt);
+ return pstmnt[executeFn]();
+ });
+ });
+}
+
+function _executeUpdate(stmnt) {
+ return _execute(stmnt, 'executeUpdate');
+}
+
+function _executeQuery(stmnt) {
+ return _execute(stmnt, 'executeQuery');
+}
+
+/*
+ * Not all SQL/JS types supported.
+ */
+function _getJsValFromResultSet(rs, type, colName) {
+ var r;
+ if (type == java.sql.Types.VARCHAR ||
+ type == java.sql.Types.LONGVARCHAR ||
+ type == java.sql.Types.CHAR) {
+ r = String(rs.getString(colName));
+ } else if (type == java.sql.Types.TIMESTAMP) {
+ var t = rs.getTimestamp(colName);
+ if (t) {
+ r = new Date(t.getTime());
+ } else {
+ r = null;
+ }
+ } else if (type == java.sql.Types.BIGINT ||
+ type == java.sql.Types.INTEGER ||
+ type == java.sql.Types.SMALLINT ||
+ type == java.sql.Types.TINYINT) {
+ r = rs.getInt(colName);
+ } else if (type == java.sql.Types.DECIMAL) {
+ r = rs.getFloat(colName);
+ } else if (type == java.sql.Types.BIT) {
+ r = rs.getBoolean(colName);
+ } else {
+ throw Error("Cannot fetch sql type ID "+type+" (columnName = "+colName+")");
+ }
+
+ if (rs.wasNull()) {
+ r = null;
+ }
+ return r;
+}
+
+function _lookupColumnType(tableName, columnName) {
+ return withConnection(function(conn) {
+ var metadata = conn.getMetaData();
+ var rs = metadata.getColumns(null, null, tableName, columnName);
+ if (!rs) {
+ throw Error("Table '"+tableName+"' does not appear to have colum '"+columnName+"'.");
+ }
+ var rsmd = rs.getMetaData();
+ var colCount = rsmd.getColumnCount();
+// rs.first();
+ rs.next();
+ var type = rs.getInt("DATA_TYPE");
+ return type;
+ });
+}
+
+/* cached, on misses calls _lookuParameterType */
+function _getParameterType(tableName, columnName) {
+ var key = [tableName, columnName].join(".");
+ return _withCache('column-types', function(cache) {
+ if (!cache[key]) {
+ cache[key] = _lookupColumnType(tableName, columnName);
+ }
+ return cache[key];
+ });
+}
+
+/*
+ * Not all SQL/JS types supported.
+ */
+function _setPreparedValues(tableName, pstmnt, keyList, obj, indexOffset) {
+ if (!indexOffset) { indexOffset = 0; }
+
+ for (var i = 1; i <= keyList.length; i++) {
+ var k = keyList[i-1];
+ var v = obj[k];
+ var j = i + indexOffset;
+
+ if (v === undefined) {
+ throw Error("value is undefined for key "+k);
+ }
+
+ if (v === null) {
+ var type = _getParameterType(tableName, k);
+ pstmnt.setNull(j, type);
+ } else if (typeof(v) == 'string') {
+ pstmnt.setString(j, v);
+ } else if (typeof(v) == 'number') {
+ pstmnt.setInt(j, v);
+ } else if (typeof(v) == 'boolean') {
+ pstmnt.setBoolean(j, v);
+ } else if (v.valueOf && v.getDate && v.getHours) {
+ pstmnt.setTimestamp(j, new java.sql.Timestamp(+v));
+ } else {
+ throw Error("Cannot insert this type of javascript object: "+typeof(v)+" (key="+k+", value = "+v+")");
+ }
+ }
+}
+
+function _resultRowToJsObj(resultSet) {
+ var resultObj = {};
+
+ var metaData = resultSet.getMetaData();
+ var colCount = metaData.getColumnCount();
+
+ for (var i = 1; i <= colCount; i++) {
+ var colName = metaData.getColumnLabel(i);
+ var type = metaData.getColumnType(i);
+ resultObj[colName] = _getJsValFromResultSet(resultSet, type, colName);
+ }
+
+ return resultObj;
+}
+
+/*
+ * Inserts the object into the given table, and returns auto-incremented ID if any.
+ */
+function insert(tableName, obj) {
+ var keyList = keys(obj);
+
+ var stmnt = "INSERT INTO "+_bq(tableName)+" (";
+ stmnt += keyList.map(function(k) { return _bq(k); }).join(', ');
+ stmnt += ") VALUES (";
+ stmnt += keyList.map(function(k) { return '?'; }).join(', ');
+ stmnt += ")";
+
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt, Statement.RETURN_GENERATED_KEYS);
+ return closing(pstmnt, function() {
+ _setPreparedValues(tableName, pstmnt, keyList, obj, 0);
+ _qdebug(stmnt);
+ pstmnt.executeUpdate();
+ var rs = pstmnt.getGeneratedKeys();
+ if (rs != null) {
+ return closing(rs, function() {
+ if (rs.next()) {
+ return rs.getInt(1);
+ }
+ });
+ }
+ });
+ });
+};
+
+/*
+ * Selects a single object given the constraintMap. If there are more
+ * than 1 objects that match, it will return a single one of them
+ * (unspecified which one). If no objects match, returns null.
+ *
+ * constraints is a javascript object of column names to values.
+ * Currently only supports string equality of constraints.
+ */
+function selectSingle(tableName, constraints) {
+ var keyList = keys(constraints);
+
+ var stmnt = "SELECT * FROM "+_bq(tableName)+" WHERE (";
+ stmnt += keyList.map(function(k) { return '('+_bq(k)+' = '+'?)'; }).join(' AND ');
+ stmnt += ')';
+ if (isMysql()) {
+ stmnt += ' LIMIT 1';
+ }
+
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ return closing(pstmnt, function() {
+ _setPreparedValues(tableName, pstmnt, keyList, constraints, 0);
+ _qdebug(stmnt);
+ var resultSet = pstmnt.executeQuery();
+ return closing(resultSet, function() {
+ if (!resultSet.next()) {
+ return null;
+ }
+ return _resultRowToJsObj(resultSet);
+ });
+ });
+ });
+}
+
+function _makeConstraintString(key, value) {
+ if (typeof(value) != 'object' || ! (value instanceof Array)) {
+ return '('+_bq(key)+' = ?)';
+ } else {
+ var comparator = value[0];
+ return '('+_bq(key)+' '+comparator+' ?)';
+ }
+}
+
+function _preparedValuesConstraints(constraints) {
+ var c = {};
+ eachProperty(constraints, function(k, v) {
+ c[k] = (typeof(v) != 'object' || ! (v instanceof Array) ? v : v[1]);
+ });
+ return c;
+}
+
+function selectMulti(tableName, constraints, options) {
+ if (!options) {
+ options = {};
+ }
+
+ var constraintKeys = keys(constraints);
+
+ var stmnt = "SELECT * FROM "+_bq(tableName)+" ";
+
+ if (constraintKeys.length > 0) {
+ stmnt += "WHERE (";
+ stmnt += constraintKeys.map(function(key) {
+ return _makeConstraintString(key, constraints[key]);
+ }).join(' AND ');
+ stmnt += ')';
+ }
+
+ if (options.orderBy) {
+ var orderEntries = [];
+ options.orderBy.split(",").forEach(function(orderBy) {
+ var asc = "ASC";
+ if (orderBy.charAt(0) == '-') {
+ orderBy = orderBy.substr(1);
+ asc = "DESC";
+ }
+ orderEntries.push(_bq(orderBy)+" "+asc);
+ });
+ stmnt += " ORDER BY "+orderEntries.join(", ");
+ }
+
+ if (options.limit) {
+ stmnt += " LIMIT "+options.limit;
+ }
+
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ return closing(pstmnt, function() {
+ _setPreparedValues(
+ tableName, pstmnt, constraintKeys,
+ _preparedValuesConstraints(constraints), 0);
+
+ _qdebug(stmnt);
+ var resultSet = pstmnt.executeQuery();
+ var resultArray = [];
+
+ return closing(resultSet, function() {
+ while (resultSet.next()) {
+ resultArray.push(_resultRowToJsObj(resultSet));
+ }
+
+ return resultArray;
+ });
+ });
+ });
+}
+
+function executeRaw(stmnt, params) {
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ return closing(pstmnt, function() {
+ for (var i = 0; i < params.length; i++) {
+ var v = params[i];
+
+ if (v === undefined) {
+ throw Error("value is undefined for key "+i);
+ }
+
+ if (typeof(v) == 'object' && v.isnull) {
+ pstmnt.setNull(i+1, v.type);
+ } else if (typeof(v) == 'string') {
+ pstmnt.setString(i+1, v);
+ } else if (typeof(v) == 'number') {
+ pstmnt.setInt(i+1, v);
+ } else if (typeof(v) == 'boolean') {
+ pstmnt.setBoolean(i+1, v);
+ } else if (v.valueOf && v.getDate && v.getHours) {
+ pstmnt.setTimestamp(i+1, new java.sql.Timestamp(+v));
+ } else {
+ throw Error("Cannot insert this type of javascript object: "+typeof(v)+" (key="+i+", value = "+v+")");
+ }
+ }
+
+ _qdebug(stmnt);
+ var resultSet = pstmnt.executeQuery();
+ var resultArray = [];
+
+ return closing(resultSet, function() {
+ while (resultSet.next()) {
+ resultArray.push(_resultRowToJsObj(resultSet));
+ }
+
+ return resultArray;
+ });
+ });
+ });
+}
+
+/* returns number of rows updated */
+function update(tableName, constraints, obj) {
+ var objKeys = keys(obj);
+ var constraintKeys = keys(constraints);
+
+ var stmnt = "UPDATE "+_bq(tableName)+" SET ";
+ stmnt += objKeys.map(function(k) { return ''+_bq(k)+' = ?'; }).join(', ');
+ stmnt += " WHERE (";
+ stmnt += constraintKeys.map(function(k) { return '('+_bq(k)+' = ?)'; }).join(' AND ');
+ stmnt += ')';
+
+ return withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ return closing(pstmnt, function() {
+ _setPreparedValues(tableName, pstmnt, objKeys, obj, 0);
+ _setPreparedValues(tableName, pstmnt, constraintKeys, constraints, objKeys.length);
+ _qdebug(stmnt);
+ return pstmnt.executeUpdate();
+ });
+ });
+}
+
+function updateSingle(tableName, constraints, obj) {
+ var count = update(tableName, constraints, obj);
+ if (count != 1) {
+ throw Error("save count != 1. instead, count = "+count);
+ }
+}
+
+function deleteRows(tableName, constraints) {
+ var constraintKeys = keys(constraints);
+ var stmnt = "DELETE FROM "+_bq(tableName)+" WHERE (";
+ stmnt += constraintKeys.map(function(k) { return '('+_bq(k)+' = ?)'; }).join(' AND ');
+ stmnt += ')';
+ withConnection(function(conn) {
+ var pstmnt = conn.prepareStatement(stmnt);
+ closing(pstmnt, function() {
+ _setPreparedValues(tableName, pstmnt, constraintKeys, constraints);
+ _qdebug(stmnt);
+ pstmnt.executeUpdate();
+ });
+ })
+}
+
+//----------------------------------------------------------------
+// table management
+//----------------------------------------------------------------
+
+/*
+ * Create a SQL table, specifying column names and types with a
+ * javascript object.
+ */
+function createTable(tableName, colspec, indices) {
+ if (doesTableExist(tableName)) {
+ return;
+ }
+
+ var stmnt = "CREATE TABLE "+_bq(tableName)+ " (";
+ stmnt += keys(colspec).map(function(k) { return (_bq(k) + ' ' + colspec[k]); }).join(', ');
+ if (indices) {
+ stmnt += ', ' + keys(indices).map(function(k) { return 'INDEX (' + _bq(k) + ')'; }).join(', ');
+ }
+ stmnt += ')'+createTableOptions();
+ _execute(stmnt);
+}
+
+function dropTable(tableName) {
+ _execute("DROP TABLE "+_bq(tableName));
+}
+
+function dropAndCreateTable(tableName, colspec, indices) {
+ if (doesTableExist(tableName)) {
+ dropTable(tableName);
+ }
+
+ return createTable(tableName, colspec, indices);
+}
+
+function renameTable(oldName, newName) {
+ _executeUpdate("RENAME TABLE "+_bq(oldName)+" TO "+_bq(newName));
+}
+
+function modifyColumn(tableName, columnName, newSpec) {
+ _executeUpdate("ALTER TABLE "+_bq(tableName)+" MODIFY "+_bq(columnName)+" "+newSpec);
+}
+
+function alterColumn(tableName, columnName, alteration) {
+ var q = "ALTER TABLE "+_bq(tableName)+" ALTER COLUMN "+_bq(columnName)+" "+alteration;
+ _executeUpdate(q);
+}
+
+function changeColumn(tableName, columnName, newSpec) {
+ var q = ("ALTER TABLE "+_bq(tableName)+" CHANGE COLUMN "+_bq(columnName)
+ +" "+newSpec);
+ _executeUpdate(q);
+}
+
+function addColumns(tableName, colspec) {
+ inTransaction(function(conn) {
+ eachProperty(colspec, function(name, definition) {
+ var stmnt = "ALTER TABLE "+_bq(tableName)+" ADD COLUMN "+_bq(name)+" "+definition;
+ _executeUpdate(stmnt);
+ });
+ });
+}
+
+function dropColumn(tableName, columnName) {
+ var stmnt = "ALTER TABLE "+_bq(tableName)+" DROP COLUMN "+_bq(columnName);
+ _executeUpdate(stmnt);
+}
+
+function listTables() {
+ return withConnection(function(conn) {
+ var metadata = conn.getMetaData();
+ var resultSet = metadata.getTables(null, null, null, null);
+ var resultArray = [];
+
+ return closing(resultSet, function() {
+ while (resultSet.next()) {
+ resultArray.push(resultSet.getString("TABLE_NAME"));
+ }
+ return resultArray;
+ });
+ });
+}
+
+function setTableEngine(tableName, engineName) {
+ var stmnt = "ALTER TABLE "+_bq(tableName)+" ENGINE="+_bq(engineName);
+ _executeUpdate(stmnt);
+}
+
+function getTableEngine(tableName) {
+ if (!isMysql()) {
+ throw Error("getTableEngine() only supported by MySQL database type.");
+ }
+
+ var tableEngines = {};
+
+ withConnection(function(conn) {
+ var stmnt = "show table status";
+ var pstmnt = conn.prepareStatement(stmnt);
+ closing(pstmnt, function() {
+ _qdebug(stmnt);
+ var resultSet = pstmnt.executeQuery();
+ closing(resultSet, function() {
+ while (resultSet.next()) {
+ var n = resultSet.getString("Name");
+ var eng = resultSet.getString("Engine");
+ tableEngines[n] = eng;
+ }
+ });
+ });
+ });
+
+ return tableEngines[tableName];
+}
+
+function createIndex(tableName, columns) {
+ var indexName = "idx_"+(columns.join("_"));
+ var stmnt = "CREATE INDEX "+_bq(indexName)+" on "+_bq(tableName)+" (";
+ stmnt += columns.map(_bq).join(", ");
+ stmnt += ")";
+ _executeUpdate(stmnt);
+}
+
diff --git a/trunk/infrastructure/framework-src/modules/stringutils.js b/infrastructure/framework-src/modules/stringutils.js
index 3fe5611..3fe5611 100644
--- a/trunk/infrastructure/framework-src/modules/stringutils.js
+++ b/infrastructure/framework-src/modules/stringutils.js
diff --git a/trunk/infrastructure/framework-src/modules/sync.js b/infrastructure/framework-src/modules/sync.js
index a222ea0..a222ea0 100644
--- a/trunk/infrastructure/framework-src/modules/sync.js
+++ b/infrastructure/framework-src/modules/sync.js
diff --git a/trunk/infrastructure/framework-src/modules/timer.js b/infrastructure/framework-src/modules/timer.js
index 01be175..01be175 100644
--- a/trunk/infrastructure/framework-src/modules/timer.js
+++ b/infrastructure/framework-src/modules/timer.js
diff --git a/trunk/infrastructure/framework-src/modules/varz.js b/infrastructure/framework-src/modules/varz.js
index 0e55d20..0e55d20 100644
--- a/trunk/infrastructure/framework-src/modules/varz.js
+++ b/infrastructure/framework-src/modules/varz.js
diff --git a/trunk/infrastructure/framework-src/modules/yuicompressor.js b/infrastructure/framework-src/modules/yuicompressor.js
index 572cc0d..572cc0d 100644
--- a/trunk/infrastructure/framework-src/modules/yuicompressor.js
+++ b/infrastructure/framework-src/modules/yuicompressor.js
diff --git a/trunk/infrastructure/framework-src/oncomet.js b/infrastructure/framework-src/oncomet.js
index b6aeda5..b6aeda5 100644
--- a/trunk/infrastructure/framework-src/oncomet.js
+++ b/infrastructure/framework-src/oncomet.js
diff --git a/trunk/infrastructure/framework-src/onerror.js b/infrastructure/framework-src/onerror.js
index f19a85f..f19a85f 100644
--- a/trunk/infrastructure/framework-src/onerror.js
+++ b/infrastructure/framework-src/onerror.js
diff --git a/trunk/infrastructure/framework-src/onprint.js b/infrastructure/framework-src/onprint.js
index 8e334fe..8e334fe 100644
--- a/trunk/infrastructure/framework-src/onprint.js
+++ b/infrastructure/framework-src/onprint.js
diff --git a/trunk/infrastructure/framework-src/onrequest.js b/infrastructure/framework-src/onrequest.js
index d76c8db..d76c8db 100644
--- a/trunk/infrastructure/framework-src/onrequest.js
+++ b/infrastructure/framework-src/onrequest.js
diff --git a/trunk/infrastructure/framework-src/onreset.js b/infrastructure/framework-src/onreset.js
index 24b000a..24b000a 100644
--- a/trunk/infrastructure/framework-src/onreset.js
+++ b/infrastructure/framework-src/onreset.js
diff --git a/trunk/infrastructure/framework-src/onsars.js b/infrastructure/framework-src/onsars.js
index 31dc8ca..31dc8ca 100644
--- a/trunk/infrastructure/framework-src/onsars.js
+++ b/infrastructure/framework-src/onsars.js
diff --git a/trunk/infrastructure/framework-src/onscheduledtask.js b/infrastructure/framework-src/onscheduledtask.js
index 810c3b5..810c3b5 100644
--- a/trunk/infrastructure/framework-src/onscheduledtask.js
+++ b/infrastructure/framework-src/onscheduledtask.js
diff --git a/trunk/infrastructure/framework-src/onshutdown.js b/infrastructure/framework-src/onshutdown.js
index 0243bf6..0243bf6 100644
--- a/trunk/infrastructure/framework-src/onshutdown.js
+++ b/infrastructure/framework-src/onshutdown.js
diff --git a/trunk/infrastructure/framework-src/onstartup.js b/infrastructure/framework-src/onstartup.js
index 61feff7..61feff7 100644
--- a/trunk/infrastructure/framework-src/onstartup.js
+++ b/infrastructure/framework-src/onstartup.js
diff --git a/trunk/infrastructure/framework-src/onsyntaxerror.js b/infrastructure/framework-src/onsyntaxerror.js
index 7129a16..7129a16 100644
--- a/trunk/infrastructure/framework-src/onsyntaxerror.js
+++ b/infrastructure/framework-src/onsyntaxerror.js
diff --git a/trunk/infrastructure/framework-src/postamble.js b/infrastructure/framework-src/postamble.js
index 76fa766..76fa766 100644
--- a/trunk/infrastructure/framework-src/postamble.js
+++ b/infrastructure/framework-src/postamble.js
diff --git a/trunk/infrastructure/framework-src/preamble.js b/infrastructure/framework-src/preamble.js
index 40f6845..40f6845 100644
--- a/trunk/infrastructure/framework-src/preamble.js
+++ b/infrastructure/framework-src/preamble.js
diff --git a/trunk/infrastructure/framework-src/syntaxerror.js b/infrastructure/framework-src/syntaxerror.js
index 801066b..801066b 100644
--- a/trunk/infrastructure/framework-src/syntaxerror.js
+++ b/infrastructure/framework-src/syntaxerror.js