aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/framework-src/modules/dispatch.js
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/framework-src/modules/dispatch.js')
-rw-r--r--trunk/infrastructure/framework-src/modules/dispatch.js149
1 files changed, 149 insertions, 0 deletions
diff --git a/trunk/infrastructure/framework-src/modules/dispatch.js b/trunk/infrastructure/framework-src/modules/dispatch.js
new file mode 100644
index 0000000..e7e3ef0
--- /dev/null
+++ b/trunk/infrastructure/framework-src/modules/dispatch.js
@@ -0,0 +1,149 @@
+/**
+ * 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 Dispatching for dynamic pages and static files rendered from disk.
+ */
+
+import("jsutils.eachProperty");
+import("stringutils");
+
+jimport("java.lang.System.out.println");
+
+//----------------------------------------------------------------
+// Util
+//----------------------------------------------------------------
+
+function PrefixMatcher(p) {
+ var rs = p.replace(/([\[\]\^\$\\\.\*\+\?\(\)\{\}\|])/g, "\\$1");
+ var r = new RegExp('^' + rs + '(.*)$');
+ return function(path) {
+ return r.exec(path);
+ }
+}
+
+// Like PrefixMatcher, but makes trailing '/' optional, as in /ep/admin or /ep/admin/.
+// If trailing '/' is omitted, will redirect to same path with trailing /.
+function DirMatcher(p) {
+ if (p.substr(-1) == '/') {
+ p = p.substr(0, p.length-1);
+ }
+ var prefixMatcher = PrefixMatcher(p+'/');
+ return function(path) {
+ if (path == p) {
+ response.redirect(p+'/');
+ }
+ return prefixMatcher(path);
+ }
+}
+
+function _pathMatches(p, loc) {
+ // returns a regex-result kind of array with length >= 1, or null
+ if (typeof(loc) == 'string') {
+ return (p == loc) ? [loc] : null;
+ }
+ if (typeof(loc) == 'function') {
+ return (loc(p) || null);
+ }
+ if (loc.exec) { // regexp
+ var r = loc.exec(p);
+ return r || null;
+ }
+ throw new Error('Uknown type of location: '+loc);
+}
+
+//----------------------------------------------------------------
+// Dispatcher
+//----------------------------------------------------------------
+
+var Dispatcher = function() {
+ this._routes = []; // Array([location, (local file path or function)])
+};
+
+Dispatcher.prototype.addLocations = function(l) {
+ var that = this;
+ l.forEach(function(x) { that._routes.push(x); });
+};
+
+Dispatcher.prototype.dispatch = function() {
+ var p = request.path;
+ var served = false;
+
+ for (var i = 0; (i < this._routes.length) && (served == false); i++) {
+ var loc = this._routes[i][0];
+ var dst = this._routes[i][1];
+
+ var match = _pathMatches(p, loc);
+ if (match) {
+ if (typeof(dst) != 'function') {
+ throw new Error('dispatch only dispatches to functions, and this is not a function: '+typeof(dst));
+ }
+
+ // call dst(group1, group2, group3, ...)
+ served = dst.apply(this, Array.prototype.slice.call(match, 1));
+ }
+ };
+
+ return served;
+};
+
+//----------------------------------------------------------------
+// fdisp
+//----------------------------------------------------------------
+
+function forward(module) {
+ return function(name) {
+ if (name === "") {
+ name = "main";
+ }
+ if (name) {
+ name = name.replace(/\-/g, '_');
+ }
+ var onreq = module['onRequest'];
+ var f = module['render_'+name];
+ var fg = module['render_'+name+'_get'];
+ var fp = module['render_'+name+'_post'];
+
+ var served = false;
+
+ if (onreq) {
+ served = onreq(name);
+ }
+
+ if (served) {
+ return true;
+ }
+
+ var method = request.method;
+ if (method == "HEAD") {
+ method = "GET";
+ }
+
+ if (f) {
+ f();
+ served = true;
+ } else if (method == "GET" && fg) {
+ fg();
+ served = true;
+ } else if (method == "POST" && fp) {
+ fp();
+ served = true;
+ }
+
+ return served;
+ };
+}
+