summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules')
-rw-r--r--sca-cpp/trunk/modules/http/curl.hpp17
-rw-r--r--sca-cpp/trunk/modules/json/json-test.cpp43
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp96
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp48
4 files changed, 135 insertions, 69 deletions
diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp
index d836eaa2f0..4e96411ec6 100644
--- a/sca-cpp/trunk/modules/http/curl.hpp
+++ b/sca-cpp/trunk/modules/http/curl.hpp
@@ -73,7 +73,7 @@ public:
private:
CURL* h;
- bool owner;
+ const bool owner;
friend CURL* handle(const CURLSession& c);
};
@@ -217,15 +217,12 @@ const failable<value> evalExpr(const value& expr, const string& url, const CURLS
if (!hasContent(res))
return mkfailure<value>(reason(res));
- // Return result
- failable<list<value> > jsres = json::readJSON(cadr<list<string> >(content(res)), cx);
- if (!hasContent(jsres))
- return mkfailure<value>(reason(jsres));
- const list<value> val = elementsToValues(content(jsres));
-
- const value rval(cadr<value>(cadr<value>(val)));
- debug(rval, "http::evalExpr::result");
- return rval;
+ // Parse and return JSON-RPC result
+ const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res)), cx);
+ if (!hasContent(rval))
+ return mkfailure<value>(reason(rval));
+ debug(content(rval), "http::evalExpr::result");
+ return content(rval);
}
/**
diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp
index b4a6ba8746..41ac24a22e 100644
--- a/sca-cpp/trunk/modules/json/json-test.cpp
+++ b/sca-cpp/trunk/modules/json/json-test.cpp
@@ -54,17 +54,18 @@ bool testJSON() {
const list<value> ac = mklist<value>(mklist<value>(element, "id", string("1234")), mklist<value>(attribute, "balance", 1000));
const list<value> cr = mklist<value>(mklist<value> (attribute, "name", string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac)));
const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr)));
+
ostringstream os;
writeJSON<ostream*>(jsonWriter, &os, c, cx);
- assert(str(os) == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}");
+ assert(str(os) == "{\"customer\":{\"@name\":\"jdoe\",\"address\":{\"@city\":\"san francisco\",\"@state\":\"ca\"},\"account\":{\"id\":\"1234\",\"@balance\":1000}}}");
}
{
const list<value> phones = mklist<value> (string("408-1234"), string("650-1234"));
- const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", string("test\ttab")), mklist<value> (element, "firstName", string("test1")));
+ const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", string("test\ttab")), mklist<value> (attribute, "firstName", string("test1")));
ostringstream os;
writeJSON<ostream*>(jsonWriter, &os, l, cx);
- assert(str(os) == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}");
+ assert(str(os) == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"@firstName\":\"test1\"}");
istringstream is(str(os));
const list<string> il = streamList(is);
@@ -75,6 +76,18 @@ bool testJSON() {
write(content(writeJSON(r, cx)), wos);
assert(str(wos) == str(os));
}
+ {
+ const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!")));
+ cout << "l: " << l << endl;
+ ostringstream wos;
+ write(content(writeJSON(valuesToElements(l), cx)), wos);
+ assert(str(wos) == "{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\"text\":\"Hello World!\"}}");
+
+ istringstream is(str(wos));
+ const list<string> il = streamList(is);
+ const list<value> r = elementsToValues(content(readJSON(il, cx)));
+ assert(r == l);
+ }
return true;
}
@@ -121,6 +134,30 @@ bool testJSONRPC() {
write(content(writeJSON(e, cx)), os);
assert(str(os) == f);
}
+ {
+ const list<value> arg = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!")));
+ const failable<list<string> > r = jsonRequest(1, "echo", mklist<value>(arg), cx);
+ ostringstream os;
+ write(content(r), os);
+ assert(str(os) == "{\"id\":1,\"method\":\"echo\",\"params\":[{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\"text\":\"Hello World!\"}}]}");
+
+ istringstream is(str(os));
+ const list<string> il = streamList(is);
+ const list<value> ir = elementsToValues(content(readJSON(il, cx)));
+ assert(car<value>(cadr<value>(caddr<value>(ir))) == arg);
+ }
+ {
+ const list<value> res = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples")) + (list<value>() + "text" + string("Hello World!")));
+ const failable<list<string> > r = jsonResult(1, res, cx);
+ ostringstream os;
+ write(content(r), os);
+ assert(str(os) == "{\"id\":1,\"result\":{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/c/samples\",\"text\":\"Hello World!\"}}}");
+
+ istringstream is(str(os));
+ const list<string> il = streamList(is);
+ const list<value> ir = elementsToValues(content(readJSON(il, cx)));
+ assert(cdr<value>(cadr<value>(ir)) == res);
+ }
return true;
}
diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp
index 1116511455..4c36b8b477 100644
--- a/sca-cpp/trunk/modules/json/json.hpp
+++ b/sca-cpp/trunk/modules/json/json.hpp
@@ -131,6 +131,22 @@ private:
};
/**
+ * Returns true if a list represents a JS array.
+ */
+const bool isJSArray(const list<value>& l) {
+ if(isNil(l))
+ return true;
+ const value v = car(l);
+ if (isSymbol(v))
+ return false;
+ if(isList(v)) {
+ if(isSymbol(car<value>(v)))
+ return false;
+ }
+ return true;
+}
+
+/**
* Converts JS properties to values.
*/
const list<value> jsPropertiesToValues(const list<value>& propertiesSoFar, JSObject* o, JSObject* i, const JSONContext& cx) {
@@ -144,11 +160,16 @@ const list<value> jsPropertiesToValues(const list<value>& propertiesSoFar, JSObj
if(!JS_GetPropertyById(cx, o, id, &jsv))
return propertiesSoFar;
const value val = jsValToValue(jsv, cx);
+
jsval idv;
JS_IdToValue(cx, id, &idv);
if(JSVAL_IS_STRING(idv)) {
- const value type = isList(val)? element : element;
- return jsPropertiesToValues(cons<value> (mklist<value> (type, JS_GetStringBytes(JSVAL_TO_STRING(idv)), val), propertiesSoFar), o, i, cx);
+ const string name = JS_GetStringBytes(JSVAL_TO_STRING(idv));
+ if (substr(name, 0, 1) == atsign)
+ return jsPropertiesToValues(cons<value>(mklist<value>(attribute, c_str(substr(name, 1)), val), propertiesSoFar), o, i, cx);
+ if (isList(val) && !isJSArray(val))
+ return jsPropertiesToValues(cons<value>(cons<value>(element, cons<value>(c_str(name), list<value>(val))), propertiesSoFar), o, i, cx);
+ return jsPropertiesToValues(cons<value> (mklist<value> (element, c_str(name), val), propertiesSoFar), o, i, cx);
}
return jsPropertiesToValues(cons(val, propertiesSoFar), o, i, cx);
}
@@ -227,39 +248,11 @@ JSObject* valuesToJSElements(JSObject* a, const list<value>& l, int i, const JSO
}
/**
- * Returns true if a list represents a JS array.
- */
-const bool isJSArray(const list<value>& l) {
- if(isNil(l))
- return false;
- const value v = car(l);
- if(isList(v)) {
- const list<value> p = v;
- if(isSymbol(car(p)))
- return false;
- }
- return true;
-}
-
-
-
-/**
- * Converts a list of values to JS properties.
- */
-JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx) {
- const jsval valueToJSVal(const value& val, const JSONContext& cx);
- if(isNil(l))
- return o;
- const list<value> p = car(l);
- jsval pv = valueToJSVal(caddr(p), cx);
- JS_SetProperty(cx, o, c_str((string)cadr(p)), &pv);
- return valuesToJSProperties(o, cdr(l), cx);
-}
-
-/**
* Converts a value to a JS val.
*/
const jsval valueToJSVal(const value& val, const JSONContext& cx) {
+ JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx);
+
switch(type(val)) {
case value::String:
case value::Symbol: {
@@ -282,16 +275,19 @@ const jsval valueToJSVal(const value& val, const JSONContext& cx) {
}
}
-const failable<bool> writeList(const list<value>& l, JSObject* o, const JSONContext& cx) {
+/**
+ * Converts a list of values to JS properties.
+ */
+JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONContext& cx) {
if (isNil(l))
- return true;
+ return o;
// Write an attribute
const value token(car(l));
if (isTaggedList(token, attribute)) {
jsval pv = valueToJSVal(attributeValue(token), cx);
- JS_SetProperty(cx, o, c_str(string(attributeName(token))), &pv);
+ JS_SetProperty(cx, o, c_str(atsign + string(attributeName(token))), &pv);
} else if (isTaggedList(token, element)) {
@@ -308,14 +304,12 @@ const failable<bool> writeList(const list<value>& l, JSObject* o, const JSONCont
JS_SetProperty(cx, o, c_str(string(elementName(token))), &pv);
// Write its children
- const failable<bool> w = writeList(elementChildren(token), child, cx);
- if (!hasContent(w))
- return w;
+ valuesToJSProperties(child, elementChildren(token), cx);
}
}
// Go on
- return writeList(cdr(l), o, cx);
+ return valuesToJSProperties(o, cdr(l), cx);
}
/**
@@ -344,11 +338,7 @@ template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *d
* Convert a list of values to a JSON document.
*/
template<typename R> const failable<R> writeJSON(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) {
- JSObject* o = JS_NewObject(cx, NULL, NULL, NULL);
- jsval val = OBJECT_TO_JSVAL(o);
- const failable<bool> w = writeList(l, o, cx);
- if (!hasContent(w))
- return mkfailure<R>(reason(w));
+ jsval val = OBJECT_TO_JSVAL(valuesToJSProperties(JS_NewObject(cx, NULL, NULL, NULL), l, cx));
WriteContext<R> wcx(reduce, initial, cx);
if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx))
@@ -367,7 +357,7 @@ const failable<list<string> > writeJSON(const list<value>& l, const JSONContext&
}
/**
- * Convert a function + params to a JSON request.
+ * Convert a list of function + params to a JSON-RPC request.
*/
const failable<list<string> > jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) {
const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("method", string(func)), mklist<value>("params", params));
@@ -375,13 +365,27 @@ const failable<list<string> > jsonRequest(const value& id, const value& func, co
}
/**
- * Convert a value to a JSON result.
+ * Convert a value to a JSON-RPC result.
*/
const failable<list<string> > jsonResult(const value& id, const value& val, JSONContext& cx) {
return writeJSON(valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))), cx);
}
/**
+ * Convert a JSON-RPC result to a value.
+ */
+const failable<value> jsonResultValue(const list<string>& s, JSONContext& cx) {
+ const failable<list<value> > jsres = json::readJSON(s, cx);
+ if (!hasContent(jsres))
+ return mkfailure<value>(reason(jsres));
+ const list<value> rval(cadr<value>(elementsToValues(content(jsres))));
+ const value val = cadr(rval);
+ if (isList(val) && !isJSArray(val))
+ return value(mklist<value>(val));
+ return val;
+}
+
+/**
* Return a portable function name from a JSON-RPC function name.
* Strip the "system." and "Service." prefixes added by some JSON-RPC clients.
*/
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
index f5c4266cc1..dfc376c55c 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.hpp
@@ -269,19 +269,45 @@ int handler(request_rec *r) {
/**
* Convert a list of component references to a list of HTTP proxy lambdas.
*/
-const value mkproxy(const value& ref, const string& base) {
+const value mkrefProxy(const value& ref, const string& base) {
return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref))));
}
-const list<value> proxies(const list<value>& refs, const string& base) {
+const list<value> refProxies(const list<value>& refs, const string& base) {
if (isNil(refs))
return refs;
- return cons(mkproxy(car(refs), base), proxies(cdr(refs), base));
+ return cons(mkrefProxy(car(refs), base), refProxies(cdr(refs), base));
}
-extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px);
+/**
+ * Convert a list of component properties to a list of lambda functions that just return
+ * the property value.
+ */
+struct propProxy {
+ const value v;
+ propProxy(const value& v) : v(v) {
+ }
+ const value operator()(unused const list<value>& params) const {
+ return v;
+ }
+};
+
+const value mkpropProxy(const value& prop) {
+ return lambda<value(const list<value>&)>(propProxy(elementValue(prop)));
+}
+
+const list<value> propProxies(const list<value>& props) {
+ if (isNil(props))
+ return props;
+ return cons(mkpropProxy(car(props)), propProxies(cdr(props)));
+}
+
+/**
+ * Evaluate a component and convert it to an applicable lambda function.
+ */
+const value evalComponent(DirConf& dc, 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 value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server, const value& comp) {
const value impl = scdl::implementation(comp);
// Convert component references to configured proxy lambdas
@@ -293,11 +319,13 @@ const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server,
<< "/references/" << string(scdl::name(comp)) << "/";
else
base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/";
- const list<value> px(proxies(scdl::references(comp), str(base)));
+ const list<value> rpx(refProxies(scdl::references(comp), str(base)));
+
+ // Convert component proxies to configured proxy lambdas
+ const list<value> ppx(propProxies(scdl::properties(comp)));
- // Evaluate the component implementation and convert it to an
- // applicable lambda function
- const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(dc.contributionPath, impl, px));
+ // Evaluate the component implementation and convert it to an applicable lambda function
+ const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(dc.contributionPath, impl, append(rpx, ppx)));
if (!hasContent(cimpl))
return reason(cimpl);
return content(cimpl);
@@ -309,7 +337,7 @@ const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server,
const list<value> componentToImplementationAssoc(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) {
if (isNil(c))
return c;
- return cons<value>(mklist<value>(scdl::name(car(c)), confImplementation(dc, sc, server, car(c))), componentToImplementationAssoc(dc, sc, server, cdr(c)));
+ return cons<value>(mklist<value>(scdl::name(car(c)), evalComponent(dc, sc, server, car(c))), componentToImplementationAssoc(dc, sc, server, cdr(c)));
}
const list<value> componentToImplementationTree(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) {