summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-24 09:27:52 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-01-24 09:27:52 +0000
commit878131a50cf9651fc8de402420b8c94696328a3c (patch)
treed0112887a0204bbf6ad9e76ae062ca4b70bc094a /sca-cpp/trunk/modules
parent1c21d758af81d880ad6e045d18f8bc62ad8be89e (diff)
Working Web service component using Axis2C 1.6. Some fixes to the JSON conversion functions to correctly handle all cases of nested objects and arrays. Added support for component properties, the Web service component has a URI property that can be configured to the address of the target Web service.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@902540 13f79535-47bb-0310-9956-ffa450edef68
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) {