summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-07-01 06:04:35 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-07-01 06:04:35 +0000
commitac8bb2ddecac09d60760ef83319b627548d0fd77 (patch)
treeb15d73262f02989d8dfe554e127e82e70b5aebe4 /sca-cpp/trunk/modules
parent54561e00c9714c9230dc1ed39f3bb548a59adeed (diff)
Minimal support for implementation.widget, using simplified (and generic) JSONRPC and ATOMPub Javascript proxies. Minor changes to the server runtime to serve reference requests from widgets. Adjust and simplified samples using the widget support.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@959521 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/modules')
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-conf1
-rw-r--r--sca-cpp/trunk/modules/json/json-test.cpp4
-rw-r--r--sca-cpp/trunk/modules/server/Makefile.am2
-rw-r--r--sca-cpp/trunk/modules/server/htdocs/js/tuscany-ref.js553
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp18
-rw-r--r--sca-cpp/trunk/modules/server/mod-wiring.cpp2
-rwxr-xr-xsca-cpp/trunk/modules/server/server-conf4
-rw-r--r--sca-cpp/trunk/modules/wsgi/scdl.py73
8 files changed, 642 insertions, 15 deletions
diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf
index 45941fc163..35c6c78254 100755
--- a/sca-cpp/trunk/modules/http/httpd-conf
+++ b/sca-cpp/trunk/modules/http/httpd-conf
@@ -38,6 +38,7 @@ ServerName $host
PidFile $root/logs/httpd.pid
# Minimal set of modules
+LoadModule alias_module ${modules_prefix}/modules/mod_alias.so
LoadModule authn_file_module ${modules_prefix}/modules/mod_authn_file.so
LoadModule authn_default_module ${modules_prefix}/modules/mod_authn_default.so
LoadModule authz_host_module ${modules_prefix}/modules/mod_authz_host.so
diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp
index b74f068710..707a785968 100644
--- a/sca-cpp/trunk/modules/json/json-test.cpp
+++ b/sca-cpp/trunk/modules/json/json-test.cpp
@@ -93,11 +93,11 @@ bool testJSON() {
bool testJSONRPC() {
JSONContext cx;
{
- const string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}");
+ const string lm("{\"id\": 1, \"method\": \"test\", \"params\": []}");
const list<value> e = content(readJSON(mklist(lm), cx));
const list<value> v = elementsToValues(e);
assert(assoc<value>("id", v) == mklist<value>("id", 1));
- assert(assoc<value>("method", v) == mklist<value>("method", string("system.listMethods")));
+ assert(assoc<value>("method", v) == mklist<value>("method", string("test")));
assert(assoc<value>("params", v) == mklist<value>("params", list<value>()));
}
{
diff --git a/sca-cpp/trunk/modules/server/Makefile.am b/sca-cpp/trunk/modules/server/Makefile.am
index 30c89da85d..4c3e5531f0 100644
--- a/sca-cpp/trunk/modules/server/Makefile.am
+++ b/sca-cpp/trunk/modules/server/Makefile.am
@@ -23,7 +23,7 @@ incldir = $(prefix)/include/modules/server
dist_mod_SCRIPTS = cpp-conf scheme-conf server-conf
moddir = $(prefix)/modules/server
-EXTRA_DIST = domain-test.composite client-test.scm server-test.scm htdocs/*.xml htdocs/*.txt htdocs/*.html
+EXTRA_DIST = domain-test.composite client-test.scm server-test.scm htdocs/*.xml htdocs/*.txt htdocs/*.html htdocs/js/*.js
mod_LTLIBRARIES = libmod_tuscany_eval.la libmod_tuscany_wiring.la
noinst_DATA = libmod_tuscany_eval.so libmod_tuscany_wiring.so
diff --git a/sca-cpp/trunk/modules/server/htdocs/js/tuscany-ref.js b/sca-cpp/trunk/modules/server/htdocs/js/tuscany-ref.js
new file mode 100644
index 0000000000..fd09a3efc7
--- /dev/null
+++ b/sca-cpp/trunk/modules/server/htdocs/js/tuscany-ref.js
@@ -0,0 +1,553 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * The JSON-RPC client code is based on Jan-Klaas' JavaScript
+ * o lait library (jsolait).
+ *
+ * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $
+ *
+ * Copyright (c) 2003-2004 Jan-Klaas Kollhof
+ * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ */
+
+/**
+ * Escape a character.
+ */
+function escapeJSONChar(c) {
+ if(c == "\"" || c == "\\") return "\\" + c;
+ else if (c == "\b") return "\\b";
+ else if (c == "\f") return "\\f";
+ else if (c == "\n") return "\\n";
+ else if (c == "\r") return "\\r";
+ else if (c == "\t") return "\\t";
+ var hex = c.charCodeAt(0).toString(16);
+ if(hex.length == 1) return "\\u000" + hex;
+ else if(hex.length == 2) return "\\u00" + hex;
+ else if(hex.length == 3) return "\\u0" + hex;
+ else return "\\u" + hex;
+}
+
+/**
+ * Encode a string into JSON format.
+ */
+function escapeJSONString(s) {
+ /* The following should suffice but Safari's regex is broken
+ (doesn't support callback substitutions)
+ return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g,
+ escapeJSONChar) + "\"";
+ */
+
+ /* Rather inefficient way to do it */
+ var parts = s.split("");
+ for(var i = 0; i < parts.length; i++) {
+ var c = parts[i];
+ if(c == '"' ||
+ c == '\\' ||
+ c.charCodeAt(0) < 32 ||
+ c.charCodeAt(0) >= 128)
+ parts[i] = escapeJSONChar(parts[i]);
+ }
+ return "\"" + parts.join("") + "\"";
+}
+
+/**
+ * Marshall objects to JSON format.
+ */
+function toJSON(o) {
+ if(o == null) {
+ return "null";
+ } else if(o.constructor == String) {
+ return escapeJSONString(o);
+ } else if(o.constructor == Number) {
+ return o.toString();
+ } else if(o.constructor == Boolean) {
+ return o.toString();
+ } else if(o.constructor == Date) {
+ return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
+ } else if(o.constructor == Array) {
+ var v = [];
+ for(var i = 0; i < o.length; i++) v.push(toJSON(o[i]));
+ return "[" + v.join(", ") + "]";
+ } else {
+ var v = [];
+ for(attr in o) {
+ if(o[attr] == null) v.push("\"" + attr + "\": null");
+ else if(typeof o[attr] == "function"); /* skip */
+ else v.push(escapeJSONString(attr) + ": " + toJSON(o[attr]));
+ }
+ return "{" + v.join(", ") + "}";
+ }
+}
+
+/**
+ * HTTPBindingClient.Exception
+ */
+HTTPBindingClient.Exception = function(code, message, javaStack) {
+ this.code = code;
+ var name;
+ if(javaStack) {
+ this.javaStack = javaStack;
+ var m = javaStack.match(/^([^:]*)/);
+ if(m) name = m[0];
+ }
+ if(name) this.name = name;
+ else this.name = "HTTPBindingClientException";
+ this.message = message;
+};
+
+HTTPBindingClient.Exception.CODE_REMOTE_EXCEPTION = 490;
+HTTPBindingClient.Exception.CODE_ERR_CLIENT = 550;
+HTTPBindingClient.Exception.CODE_ERR_PARSE = 590;
+HTTPBindingClient.Exception.CODE_ERR_NOMETHOD = 591;
+HTTPBindingClient.Exception.CODE_ERR_UNMARSHALL = 592;
+HTTPBindingClient.Exception.CODE_ERR_MARSHALL = 593;
+
+HTTPBindingClient.Exception.prototype = new Error();
+HTTPBindingClient.Exception.prototype.toString = function(code, msg)
+{
+ return this.name + ": " + this.message;
+};
+
+/**
+ * Default top level exception handler
+ */
+HTTPBindingClient.default_ex_handler = function(e) { alert(e); };
+
+
+/**
+ * Client settable variables
+ */
+HTTPBindingClient.toplevel_ex_handler = HTTPBindingClient.default_ex_handler;
+HTTPBindingClient.profile_async = false;
+HTTPBindingClient.max_req_active = 1;
+HTTPBindingClient.requestId = 1;
+
+
+/**
+ * HTTPBindingClient implementation
+ */
+HTTPBindingClient.prototype._createApplyMethod = function() {
+ var fn = function() {
+ var args = [];
+ var callback = null;
+ var methodName = arguments[0];
+ for(var i = 1; i < arguments.length; i++) args.push(arguments[i]);
+
+ if(typeof args[args.length - 1] == "function") callback = args.pop();
+
+ var req = fn.client._makeRequest.call(fn.client, methodName, args, callback);
+ if(callback == null) {
+ return fn.client._sendRequest.call(fn.client, req);
+ } else {
+ HTTPBindingClient.async_requests.push(req);
+ HTTPBindingClient.kick_async();
+ return req.requestId;
+ }
+ };
+ fn.client = this;
+ return fn;
+};
+
+HTTPBindingClient._getCharsetFromHeaders = function(http) {
+ try {
+ var contentType = http.getResponseHeader("Content-type");
+ var parts = contentType.split(/\s*;\s*/);
+ for(var i = 0; i < parts.length; i++) {
+ if(parts[i].substring(0, 8) == "charset=")
+ return parts[i].substring(8, parts[i].length);
+ }
+ } catch (e) {}
+ return "UTF-8";
+};
+
+/**
+ * Async queue globals
+ */
+HTTPBindingClient.async_requests = [];
+HTTPBindingClient.async_inflight = {};
+HTTPBindingClient.async_responses = [];
+HTTPBindingClient.async_timeout = null;
+HTTPBindingClient.num_req_active = 0;
+
+HTTPBindingClient._async_handler = function() {
+ HTTPBindingClient.async_timeout = null;
+
+ while(HTTPBindingClient.async_responses.length > 0) {
+ var res = HTTPBindingClient.async_responses.shift();
+ if(res.canceled) continue;
+ if(res.profile) res.profile.dispatch = new Date();
+ try {
+ res.cb(res.result, res.ex, res.profile);
+ } catch(e) {
+ HTTPBindingClient.toplevel_ex_handler(e);
+ }
+ }
+
+ while(HTTPBindingClient.async_requests.length > 0 && HTTPBindingClient.num_req_active < HTTPBindingClient.max_req_active) {
+ var req = HTTPBindingClient.async_requests.shift();
+ if(req.canceled) continue;
+ req.client._sendRequest.call(req.client, req);
+ }
+};
+
+HTTPBindingClient.kick_async = function() {
+ if(HTTPBindingClient.async_timeout == null)
+ HTTPBindingClient.async_timeout = setTimeout(HTTPBindingClient._async_handler, 0);
+};
+
+HTTPBindingClient.cancelRequest = function(requestId) {
+ /* If it is in flight then mark it as canceled in the inflight map
+ and the XMLHttpRequest callback will discard the reply. */
+ if(HTTPBindingClient.async_inflight[requestId]) {
+ HTTPBindingClient.async_inflight[requestId].canceled = true;
+ return true;
+ }
+
+ /* If its not in flight yet then we can just mark it as canceled in
+ the the request queue and it will get discarded before being sent. */
+ for(var i in HTTPBindingClient.async_requests) {
+ if(HTTPBindingClient.async_requests[i].requestId == requestId) {
+ HTTPBindingClient.async_requests[i].canceled = true;
+ return true;
+ }
+ }
+
+ /* It may have returned from the network and be waiting for its callback
+ to be dispatched, so mark it as canceled in the response queue
+ and the response will get discarded before calling the callback. */
+ for(var i in HTTPBindingClient.async_responses) {
+ if(HTTPBindingClient.async_responses[i].requestId == requestId) {
+ HTTPBindingClient.async_responses[i].canceled = true;
+ return true;
+ }
+ }
+
+ return false;
+};
+
+HTTPBindingClient.prototype._makeRequest = function(methodName, args, cb) {
+ var req = {};
+ req.client = this;
+ req.requestId = HTTPBindingClient.requestId++;
+
+ var obj = {};
+ obj.id = req.requestId;
+ if (this.objectID)
+ obj.method = ".obj#" + this.objectID + "." + methodName;
+ else
+ obj.method = methodName;
+ obj.params = args;
+
+ if (cb) req.cb = cb;
+ if (HTTPBindingClient.profile_async)
+ req.profile = { "submit": new Date() };
+ req.data = toJSON(obj);
+
+ return req;
+};
+
+HTTPBindingClient.prototype._sendRequest = function(req) {
+ if(req.profile) req.profile.start = new Date();
+
+ /* Get free http object from the pool */
+ var http = HTTPBindingClient.poolGetHTTPRequest();
+ HTTPBindingClient.num_req_active++;
+
+ /* Send the request */
+ http.open("POST", this.uri, (req.cb != null));
+
+ /* setRequestHeader is missing in Opera 8 Beta */
+ try {
+ http.setRequestHeader("Content-type", "text/plain");
+ } catch(e) {}
+
+ /* Construct call back if we have one */
+ if(req.cb) {
+ var self = this;
+ http.onreadystatechange = function() {
+ if(http.readyState == 4) {
+ http.onreadystatechange = function () {};
+ var res = { "cb": req.cb, "result": null, "ex": null};
+ if (req.profile) {
+ res.profile = req.profile;
+ res.profile.end = new Date();
+ }
+ try { res.result = self._handleResponse(http); }
+ catch(e) { res.ex = e; }
+ if(!HTTPBindingClient.async_inflight[req.requestId].canceled)
+ HTTPBindingClient.async_responses.push(res);
+ delete HTTPBindingClient.async_inflight[req.requestId];
+ HTTPBindingClient.kick_async();
+ }
+ };
+ } else {
+ http.onreadystatechange = function() {};
+ }
+
+ HTTPBindingClient.async_inflight[req.requestId] = req;
+
+ try {
+ http.send(req.data);
+ } catch(e) {
+ HTTPBindingClient.poolReturnHTTPRequest(http);
+ HTTPBindingClient.num_req_active--;
+ throw new HTTPBindingClient.Exception(HTTPBindingClient.Exception.CODE_ERR_CLIENT, "Connection failed");
+ }
+
+ if(!req.cb) return this._handleResponse(http);
+};
+
+HTTPBindingClient.prototype._handleResponse = function(http) {
+ /* Get the charset */
+ if(!this.charset) {
+ this.charset = HTTPBindingClient._getCharsetFromHeaders(http);
+ }
+
+ /* Get request results */
+ var status, statusText, data;
+ try {
+ status = http.status;
+ statusText = http.statusText;
+ data = http.responseText;
+ } catch(e) {
+ HTTPBindingClient.poolReturnHTTPRequest(http);
+ HTTPBindingClient.num_req_active--;
+ HTTPBindingClient.kick_async();
+ throw new HTTPBindingClient.Exception(HTTPBindingClient.Exception.CODE_ERR_CLIENT, "Connection failed");
+ }
+
+ /* Return http object to the pool; */
+ HTTPBindingClient.poolReturnHTTPRequest(http);
+ HTTPBindingClient.num_req_active--;
+
+ /* Unmarshall the response */
+ if(status != 200) {
+ throw new HTTPBindingClient.Exception(status, statusText);
+ }
+ var obj;
+ try {
+ eval("obj = " + data);
+ } catch(e) {
+ throw new HTTPBindingClient.Exception(550, "error parsing result");
+ }
+ if(obj.error)
+ throw new HTTPBindingClient.Exception(obj.error.code, obj.error.msg, obj.error.trace);
+ var res = obj.result;
+
+ /* Handle CallableProxy */
+ if(res && res.objectID && res.JSONRPCType == "CallableReference")
+ return new HTTPBindingClient(this.uri, res.objectID);
+
+ return res;
+};
+
+
+/**
+ * XMLHttpRequest wrapper code
+ */
+HTTPBindingClient.http_spare = [];
+HTTPBindingClient.http_max_spare = 8;
+
+HTTPBindingClient.poolGetHTTPRequest = function() {
+ if(HTTPBindingClient.http_spare.length > 0) {
+ return HTTPBindingClient.http_spare.pop();
+ }
+ return HTTPBindingClient.getHTTPRequest();
+};
+
+HTTPBindingClient.poolReturnHTTPRequest = function(http) {
+ if(HTTPBindingClient.http_spare.length >= HTTPBindingClient.http_max_spare)
+ delete http;
+ else
+ HTTPBindingClient.http_spare.push(http);
+};
+
+HTTPBindingClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0",
+ "MSXML2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP" ];
+
+HTTPBindingClient.getHTTPRequest = function() {
+ /* Mozilla XMLHttpRequest */
+ try {
+ HTTPBindingClient.httpObjectName = "XMLHttpRequest";
+ return new XMLHttpRequest();
+ } catch(e) {}
+
+ /* Microsoft MSXML ActiveX */
+ for (var i=0; i < HTTPBindingClient.msxmlNames.length; i++) {
+ try {
+ HTTPBindingClient.httpObjectName = HTTPBindingClient.msxmlNames[i];
+ return new ActiveXObject(HTTPBindingClient.msxmlNames[i]);
+ } catch (e) {}
+ }
+
+ /* None found */
+ HTTPBindingClient.httpObjectName = null;
+ throw new HTTPBindingClient.Exception(0, "Can't create XMLHttpRequest object");
+};
+
+
+HTTPBindingClient.prototype.get = function(id, responseFunction) {
+ var xhr = this.createXMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ var strDocument = xhr.responseText;
+ var xmlDocument = xhr.responseXML;
+ if(!xmlDocument || xmlDocument.childNodes.length==0){
+ xmlDocument = (new DOMParser()).parseFromString(strDocument, "text/xml");
+ }
+ if (responseFunction != null) responseFunction(xmlDocument);
+ } else {
+ alert("get - Error getting data from the server");
+ }
+ }
+ }
+ xhr.open("GET", this.uri + '/' + id, true);
+ xhr.send(null);
+}
+
+HTTPBindingClient.prototype.post = function (entry, responseFunction) {
+ var xhr = this.createXMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 201) {
+ var strDocument = xhr.responseText;
+ var xmlDocument = xhr.responseXML;
+ if(!xmlDocument || xmlDocument.childNodes.length==0){
+ xmlDocument = (new DOMParser()).parseFromString(strDocument, "text/xml");
+ }
+ if (responseFunction != null) responseFunction(xmlDocument);
+ } else {
+ alert("post - Error getting data from the server");
+ }
+ }
+ }
+ xhr.open("POST", this.uri, true);
+ xhr.setRequestHeader("Content-Type", "application/atom+xml");
+ xhr.send(entry);
+}
+
+HTTPBindingClient.prototype.put = function (id, entry, responseFunction) {
+ var xhr = this.createXMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ var strDocument = xhr.responseText;
+ var xmlDocument = xhr.responseXML;
+ if(!xmlDocument || xmlDocument.childNodes.length==0){
+ xmlDocument = (new DOMParser()).parseFromString(strDocument, "text/xml");
+ }
+ if (responseFunction != null) responseFunction(xmlDocument);
+ } else {
+ alert("put - Error getting data from the server");
+ }
+ }
+ }
+ xhr.open("PUT", this.uri + '/' + id, true);
+ xhr.setRequestHeader("Content-Type", "application/atom+xml");
+ xhr.send(entry);
+}
+
+HTTPBindingClient.prototype.del = function (id, responseFunction) {
+ var xhr = this.createXMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ if (responseFunction != null) responseFunction();
+ } else {
+ alert("delete - Error getting data from the server");
+ }
+ }
+ }
+ xhr.open("DELETE", this.uri + '/' + id, true);
+ xhr.send(null);
+}
+
+HTTPBindingClient.prototype.createXMLHttpRequest = function () {
+ /* Mozilla XMLHttpRequest */
+ try { return new XMLHttpRequest(); } catch(e) {}
+
+ /* Microsoft MSXML ActiveX */
+ for (var i = 0; i < HTTPBindingClient.msxmlNames.length; i++) {
+ try { return new ActiveXObject(HTTPBindingClient.msxmlNames[i]); } catch (e) {}
+ }
+ alert("XML http request not supported");
+ return null;
+}
+
+/**
+ * Create Tuscany namespace.
+ */
+var tuscany;
+if (!tuscany)
+ tuscany = {};
+if (!tuscany.sca)
+ tuscany.sca = {};
+
+/**
+ * Configure component name
+ */
+tuscany.sca.componentName = "Default";
+
+tuscany.sca.Component = function(name) {
+ tuscany.sca.componentName = name;
+ return name
+}
+
+/**
+ * Construct an HTTPBindingClient.
+ */
+function HTTPBindingClient(cname, uri, objectID) {
+ this.uri = "/references/" + cname + "/" + uri;
+ this.objectID = objectID;
+ this.apply = this._createApplyMethod();
+
+ if (typeof DOMParser == "undefined") {
+ DOMParser = function () {}
+
+ DOMParser.prototype.parseFromString = function (str, contentType) {
+ if (typeof ActiveXObject != "undefined") {
+ var d = new ActiveXObject("MSXML.DomDocument");
+ d.loadXML(str);
+ return d;
+ } else if (typeof XMLHttpRequest != "undefined") {
+ var req = new XMLHttpRequest;
+ req.open("GET", "data:" + (contentType || "application/xml") +
+ ";charset=utf-8," + encodeURIComponent(str), false);
+ if (req.overrideMimeType) {
+ req.overrideMimeType(contentType);
+ }
+ req.send(null);
+ return req.responseXML;
+ }
+ }
+ }
+};
+
+/**
+ * Construct a reference proxy
+ */
+tuscany.sca.Reference = function(name) {
+ return new HTTPBindingClient(tuscany.sca.componentName, name);
+}
+
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
index e46d8ba78a..14e5f40e9b 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.hpp
@@ -358,6 +358,22 @@ const list<value> propProxies(const list<value>& props) {
/**
* Evaluate a component and convert it to an applicable lambda function.
*/
+struct implementationFailure {
+ const value reason;
+ implementationFailure(const value& r) : reason(r) {
+ }
+
+ // Default implementation representing an implementation that
+ // couldn't be evaluated. Report the evaluation error on all
+ // subsequent calls expect start/stop.
+ const value operator()(unused const list<value>& params) const {
+ const value func = car(params);
+ if (func == "start" || func == "stop")
+ return mklist<value>(lambda<value(const list<value>&)>());
+ return mklist<value>(value(), reason);
+ }
+};
+
const value evalComponent(ServerConf& sc, server_rec& server, const value& comp) {
extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle);
@@ -380,7 +396,7 @@ const value evalComponent(ServerConf& sc, server_rec& server, const value& comp)
// Evaluate the component implementation and convert it to an applicable lambda function
const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(sc.contributionPath, impl, append(rpx, ppx), sc.lifecycle));
if (!hasContent(cimpl))
- return reason(cimpl);
+ return lambda<value(const list<value>&)>(implementationFailure(reason(cimpl)));
return content(cimpl);
}
diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp
index 296181acfa..7f41a7e03d 100644
--- a/sca-cpp/trunk/modules/server/mod-wiring.cpp
+++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp
@@ -107,7 +107,7 @@ int translateReference(request_rec *r) {
}
// Route to a relative target URI using a local internal redirect
- r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/components/") + target));
+ r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/components/") + substr(target, 0, find(target, '/'))));
r->handler = "mod_tuscany_wiring";
return OK;
}
diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf
index ed5ead4cf5..c430d53de2 100755
--- a/sca-cpp/trunk/modules/server/server-conf
+++ b/sca-cpp/trunk/modules/server/server-conf
@@ -23,6 +23,7 @@ root=`readlink -f $1`
host=`cat $root/conf/httpd.conf | grep ServerName | awk '{ print $2 }'`
port=`cat $root/conf/httpd.conf | grep Listen | tail -1 | awk '{ print $2 }'`
+
ssl=`cat $root/conf/httpd.conf | grep "SSLEngine" | awk '{ print $2 }'`
if [ "$ssl" = "on" ]; then
protocol="https"
@@ -44,4 +45,7 @@ cat >>$root/conf/httpd.conf <<EOF
LoadModule mod_tuscany_wiring $here/libmod_tuscany_wiring.so
SCAWiringServerName $protocol://$host:$port
+Alias /js/tuscany-ref.js $here/htdocs/js/tuscany-ref.js
+
EOF
+
diff --git a/sca-cpp/trunk/modules/wsgi/scdl.py b/sca-cpp/trunk/modules/wsgi/scdl.py
index af332d0249..2a4a667173 100644
--- a/sca-cpp/trunk/modules/wsgi/scdl.py
+++ b/sca-cpp/trunk/modules/wsgi/scdl.py
@@ -18,6 +18,7 @@
# SCDL parsing functions
from xml.etree.cElementTree import iterparse
+from sys import stderr
from util import *
from httputil import *
@@ -86,8 +87,8 @@ def references(e):
if match(car(e), "start", "reference") == False:
return references(cdr(e))
if "target" in att(car(e)):
- return cons(car(tokens(att(car(e))["target"])), references(cdr(e)))
- return cons(binding(e), references(cdr(e)))
+ return cons((att(car(e))["name"], car(tokens(att(car(e))["target"]))), references(cdr(e)))
+ return cons((att(car(e))["name"], binding(e)), references(cdr(e)))
# Return the list of properties under a SCDL component element
def properties(e):
@@ -116,7 +117,7 @@ def components(e):
if match(car(e), "start", "component") == False:
return components(cdr(e))
n = name(e)
- return cons(mkcomponent(n, implementation(e), cons(("components", n), services(e)), references(e), properties(e)), components(cdr(e)))
+ return cons(mkcomponent(n, implementation(e), services(e), references(e), properties(e)), components(cdr(e)))
# Find a component with a given name
def nameToComponent(name, comps):
@@ -136,28 +137,80 @@ def matchingURI(u, svcs):
# Return the (service URI, component) pair matching a given URI
def uriToComponent(u, comps):
+ if car(u) == "components":
+ return componentURIToComponent(u, comps)
+ if car(u) == "references":
+ return referenceURIToComponent(u, comps)
+ return serviceURIToComponent(u, comps)
+
+def serviceURIToComponent(u, comps):
if comps == ():
return (None, None)
m = matchingURI(u, car(comps).svcs)
if m != None:
return (m, car(comps))
- return uriToComponent(u, cdr(comps))
+ return serviceURIToComponent(u, cdr(comps))
+
+def componentURIToComponent(u, comps):
+ comp = nameToComponent(cadr(u), comps)
+ if comps == None:
+ return (None, None)
+ return (u[0:2], comp)
+
+def referenceURIToComponent(u, comps):
+ sc = nameToComponent(cadr(u), comps)
+ if sc == None:
+ return (None, None)
+
+ def referenceToComponent(r, refs):
+ if refs == ():
+ return None
+ if r == car(car(refs)):
+ return cadr(car(refs))
+ return referenceToComponent(r, cdr(refs))
+
+ tn = referenceToComponent(caddr(u), sc.refs)
+ if tn == None:
+ return (None, None)
+ tc = nameToComponent(tn, comps)
+ if tc == None:
+ return (None, None)
+ return (u[0:3], tc)
# Evaluate a reference, return a proxy to the resolved component or an
# HTTP client configured with the reference target uri
def evalReference(r, comps):
- if r.startswith("http://") or r.startswith("https://"):
- return mkclient(r)
- return nameToComponent(r, comps)
-
-# Evaluate a component, resolve its implementation and references
+ t = cadr(r)
+ if t.startswith("http://") or t.startswith("https://"):
+ return mkclient(t)
+ return nameToComponent(t, comps)
+
+# Evaluate a property, return a lambda function returning the property
+# value. The user and email properties are configured with the values
+# from the HTTP request, if any
+def evalProperty(p):
+ if (isTaggedList(p, "user")):
+ return lambda: userProperty(cadr(p))
+ if (isTaggedList(p, "email")):
+ return lambda: emailProperty(cadr(p))
+ return lambda: p
+
+def userProperty(v):
+ return "nobody"
+
+def emailProperty(v):
+ return "nobody@nowhere.com"
+
+# Evaluate a component, resolve its implementation, references and
+# properties
def evalComponent(comp, comps):
comp.mod = __import__(comp.impl)
# Make a list of proxy lambda functions for the component references and properties
# A reference proxy is the callable lambda function of the component wired to the reference
# A property proxy is a lambda function that returns the value of the property
- comp.proxies = tuple(map(lambda r: evalReference(r, comps), comp.refs)) + tuple(map(lambda v: lambda: v, comp.props))
+ print >> stderr, "evalComponent", comp.impl, comp.svcs, comp.refs, comp.props
+ comp.proxies = tuple(map(lambda r: evalReference(r, comps), comp.refs)) + tuple(map(lambda p: evalProperty(p), comp.props))
return comp