summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-03-13 19:24:08 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-03-13 19:24:08 +0000
commita1581d7fde2b8663ad07a2d3d675776164369f26 (patch)
tree3e1e70b51aa3b64babf62363e1763cb2be08a2a3
parentd1d9ba0e29baed02a052dae81b049d00a1454bf8 (diff)
Add Javascript functions and test cases to help work with JSON.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1081204 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--sca-cpp/trunk/modules/js/Makefile.am8
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/component.js4
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/jsonutil.js259
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/util.js34
-rw-r--r--sca-cpp/trunk/modules/js/js-eval.cpp55
-rw-r--r--sca-cpp/trunk/modules/js/json-test.js51
-rwxr-xr-xsca-cpp/trunk/modules/js/util-test30
-rwxr-xr-xsca-cpp/trunk/modules/server/server-conf5
8 files changed, 441 insertions, 5 deletions
diff --git a/sca-cpp/trunk/modules/js/Makefile.am b/sca-cpp/trunk/modules/js/Makefile.am
index 8c88f32c0f..e525332107 100644
--- a/sca-cpp/trunk/modules/js/Makefile.am
+++ b/sca-cpp/trunk/modules/js/Makefile.am
@@ -25,5 +25,9 @@ EXTRA_DIST = htdocs/*.js htdocs/*.css
js_test_SOURCES = js-test.cpp
js_test_LDFLAGS = -lmozjs
-noinst_PROGRAMS = js-test
-TESTS = js-test
+js_eval_SOURCES = js-eval.cpp
+js_eval_LDFLAGS = -lmozjs
+
+noinst_PROGRAMS = js-test js-eval
+dist_noinst_SCRIPTS = util-test
+TESTS = js-test util-test
diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js
index ecbcdeda5b..8e25292018 100644
--- a/sca-cpp/trunk/modules/js/htdocs/component.js
+++ b/sca-cpp/trunk/modules/js/htdocs/component.js
@@ -31,11 +31,11 @@
* Client component wiring API, supporting JSON and ATOM bindings.
*/
+var JSONClient = {};
+
/**
* Escape a character.
*/
-var JSONClient = {};
-
JSONClient.escapeJSONChar = function(c) {
if(c == "\"" || c == "\\") return "\\" + c;
if (c == "\b") return "\\b";
diff --git a/sca-cpp/trunk/modules/js/htdocs/jsonutil.js b/sca-cpp/trunk/modules/js/htdocs/jsonutil.js
new file mode 100644
index 0000000000..1a1a027e88
--- /dev/null
+++ b/sca-cpp/trunk/modules/js/htdocs/jsonutil.js
@@ -0,0 +1,259 @@
+/*
+ * 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.
+ */
+
+/**
+ * JSON data conversion functions.
+ */
+var json = {};
+
+/**
+ * JSON exceptions.
+ */
+json.Exception = function(code, message) {
+ this.name = "JSONException";
+ this.code = code;
+ this.message = message;
+};
+
+json.Exception.prototype = new Error();
+
+json.Exception.prototype.toString = function() {
+ return this.name + ": " + this.message;
+};
+
+/**
+ * Return true if a list represents a JS array.
+ */
+json.isJSArray = function(l) {
+ if (isNil(l))
+ return true;
+ var v = car(l);
+ if (isSymbol(v))
+ return false;
+ if (isList(v))
+ if (!isNil(v) && isSymbol(car(v)))
+ return false;
+ return true;
+};
+
+/**
+ * Converts JSON properties to values.
+ */
+json.jsPropertiesToValues = function(propertiesSoFar, o, i) {
+ if (isNil(i))
+ return propertiesSoFar;
+ var p = car(i);
+ var jsv = o[p];
+ var v = json.jsValToValue(jsv);
+
+ if (typeof p == 'string') {
+ var n = '' + p;
+ if (n.slice(0, 1) == '@')
+ return json.jsPropertiesToValues(cons(mklist(attribute, "'" + n.slice(1), v), propertiesSoFar), o, cdr(i));
+ if (isList(v) && !json.isJSArray(v))
+ return json.jsPropertiesToValues(cons(cons(element, cons("'" + n, v)), propertiesSoFar), o, cdr(i));
+ return json.jsPropertiesToValues(cons(mklist(element, "'" + n, v), propertiesSoFar), o, cdr(i));
+ }
+ return json.jsPropertiesToValues(cons(v, propertiesSoFar), o, cdr(i));
+};
+
+/**
+ * Converts a JSON val to a value.
+ */
+json.jsValToValue = function(jsv) {
+ if (isList(jsv))
+ return json.jsPropertiesToValues(mklist(), jsv, reverse(range(0, jsv.length)));
+ if (typeof jsv == 'object')
+ return json.jsPropertiesToValues(mklist(), jsv, properties(jsv));
+ if (typeof jsv == 'string')
+ return '' + jsv;
+ return jsv;
+}
+
+/**
+ * Return true if a list of strings contains a JSON document.
+ */
+json.isJSON = function(l) {
+ if (isNil(l))
+ return false;
+ var s = car(l).slice(0, 1);
+ return s == "[" || s == "{";
+};
+
+/**
+ * Convert a list of strings representing a JSON document to a list of values.
+ */
+json.readJSON = function(l) {
+ var s = writeStrings(l);
+ var obj;
+ eval('obj = { \"val\": ' + s + " }");
+ return json.jsValToValue(obj.val);
+};
+
+/**
+ * Convert a list of values to JSON array elements.
+ */
+json.valuesToJSElements = function(a, l, i) {
+ if (isNil(l))
+ return a;
+ var pv = json.valueToJSVal(car(l));
+ a[i] = pv
+ return json.valuesToJSElements(a, cdr(l), i + 1);
+};
+
+/**
+ * Convert a value to a JSON value.
+ */
+json.valueToJSVal = function(v) {
+ if (!isList(v))
+ return v;
+ if (json.isJSArray(v))
+ return json.valuesToJSElements(range(0, v.length), v, 0);
+ return json.valuesToJSProperties({}, v);
+};
+
+/**
+ * Convert a list of values to JSON properties.
+ */
+json.valuesToJSProperties = function(o, l) {
+ if (isNil(l))
+ return o;
+ var token = car(l);
+ if (isTaggedList(token, attribute)) {
+ var pv = json.valueToJSVal(attributeValue(token));
+ o['@' + attributeName(token).slice(1)] = pv;
+ } else if (isTaggedList(token, element)) {
+ if (elementHasValue(token)) {
+ var pv = json.valueToJSVal(elementValue(token));
+ o[elementName(token).slice(1)] = pv;
+ } else {
+ var child = {};
+ o[elementName(token).slice(1)] = child;
+ json.valuesToJSProperties(child, elementChildren(token));
+ }
+ }
+ return json.valuesToJSProperties(o, cdr(l));
+};
+
+/**
+ * Convert a list of values to a list of strings representing a JSON document.
+ */
+json.writeJSON = function(l) {
+ var jsv;
+ if (json.isJSArray(l))
+ jsv = json.valuesToJSElements(range(0, l.length), l, 0);
+ else
+ jsv = json.valuesToJSProperties({}, l);
+ var s = json.toJSON(jsv);
+ return mklist(s);
+}
+
+/**
+ * Convert a list + params to a JSON-RPC request.
+ */
+json.jsonRequest = function(id, func, params) {
+ var r = mklist(mklist("'id", id), mklist("'method", func), mklist("'params", params));
+ return json.writeJSON(valuesToElements(r));
+};
+
+/**
+ * Convert a value to a JSON-RPC result.
+ */
+json.jsonResult = function(id, val) {
+ return json.writeJSON(valuesToElements(mklist(mklist("'id", id), mklist("'result", val))));
+};
+
+/**
+ * Convert a JSON-RPC result to a value.
+ */
+json.jsonResultValue = function(s) {
+ var jsres = json.readJSON(s);
+ var res = elementsToValues(jsres);
+ var val = cadr(assoc("'result", res));
+ if (isList(val) && !json.isJSArray(val))
+ return mklist(val);
+ return val;
+};
+
+/**
+ * Escape a character.
+ */
+json.escapeJSONChar = function(c) {
+ if(c == "\"" || c == "\\") return "\\" + c;
+ if (c == "\b") return "\\b";
+ if (c == "\f") return "\\f";
+ if (c == "\n") return "\\n";
+ if (c == "\r") return "\\r";
+ if (c == "\t") return "\\t";
+ var hex = c.charCodeAt(0).toString(16);
+ if(hex.length == 1) return "\\u000" + hex;
+ if(hex.length == 2) return "\\u00" + hex;
+ if(hex.length == 3) return "\\u0" + hex;
+ return "\\u" + hex;
+};
+
+/**
+ * Encode a string into JSON format.
+ */
+json.escapeJSONString = function(s) {
+ // The following should suffice but Safari's regex is broken (doesn't support callback substitutions)
+ // return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, json.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] = json.escapeJSONChar(parts[i]);
+ }
+ return "\"" + parts.join("") + "\"";
+};
+
+/**
+ * Marshall objects to JSON format.
+ */
+json.toJSON = function(o) {
+ if(o == null)
+ return "null";
+ if(o.constructor == String)
+ return json.escapeJSONString(o);
+ if(o.constructor == Number)
+ return o.toString();
+ if(o.constructor == Boolean)
+ return o.toString();
+ if(o.constructor == Date)
+ return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
+ if(o.constructor == Array) {
+ var v = [];
+ for(var i = 0; i < o.length; i++)
+ v.push(json.toJSON(o[i]));
+ return "[" + v.join(", ") + "]";
+ }
+ var v = [];
+ for(attr in o) {
+ if(o[attr] == null)
+ v.push("\"" + attr + "\": null");
+ else if(typeof o[attr] == "function")
+ ; // Skip
+ else
+ v.push(json.escapeJSONString(attr) + ": " + json.toJSON(o[attr]));
+ }
+ return "{" + v.join(", ") + "}";
+};
+
diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js
index 20af741c6d..512e3c26d5 100644
--- a/sca-cpp/trunk/modules/js/htdocs/util.js
+++ b/sca-cpp/trunk/modules/js/htdocs/util.js
@@ -72,6 +72,13 @@ function reverse(l) {
return l.slice(0).reverse();
}
+function range(a, b) {
+ var l = new Array();
+ for (var x = a; x < b; x++)
+ l.push(x);
+ return l;
+}
+
function isNil(v) {
if (v == null || typeof v == 'undefined' || (v.constructor == Array && v.length == 0))
return true;
@@ -85,7 +92,7 @@ function isSymbol(v) {
}
function isString(v) {
- if (typeof v == 'string')
+ if (typeof v == 'string' && v.slice(0, 1) != "'")
return true;
return false;
}
@@ -199,6 +206,21 @@ function debug(o) {
}
/**
+ * Simple assert function.
+ */
+function AssertException() {
+}
+
+AssertException.prototype.toString = function () {
+ return 'AssertException';
+};
+
+function assert(exp) {
+ if (!exp)
+ throw new AssertException();
+}
+
+/**
* Write a list of strings.
*/
function writeStrings(l) {
@@ -252,6 +274,16 @@ function unmemo(obj) {
}
/**
+ * Returns a list of the properties of an object.
+ */
+function properties(o) {
+ var a = new Array();
+ for (p in o)
+ a.push(p);
+ return a;
+}
+
+/**
* Functions with side effects. Use with moderation.
*/
diff --git a/sca-cpp/trunk/modules/js/js-eval.cpp b/sca-cpp/trunk/modules/js/js-eval.cpp
new file mode 100644
index 0000000000..ee0fa89b31
--- /dev/null
+++ b/sca-cpp/trunk/modules/js/js-eval.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Evaluate a JavaScript script.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "fstream.hpp"
+#include "string.hpp"
+#include "eval.hpp"
+
+namespace tuscany {
+namespace js {
+
+bool eval() {
+ ostringstream os;
+ for(;;) {
+ int c = cin.get();
+ if (c == -1)
+ break;
+ os << (char)c;
+ }
+ failable<value> v = evalScript(str(os));
+ assert(hasContent(v));
+ cout << v;
+ return true;
+}
+
+}
+}
+
+int main() {
+ tuscany::js::eval();
+ return 0;
+}
diff --git a/sca-cpp/trunk/modules/js/json-test.js b/sca-cpp/trunk/modules/js/json-test.js
new file mode 100644
index 0000000000..5cc93a86eb
--- /dev/null
+++ b/sca-cpp/trunk/modules/js/json-test.js
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test JSON data encoding functions.
+ */
+function testJSON() {
+ var ad = mklist(mklist(attribute, "'city", "san francisco"), mklist(attribute, "'state", "ca"));
+ var ac = mklist(mklist(element, "'id", "1234"), mklist(attribute, "'balance", 1000));
+ var cr = mklist(mklist(attribute, "'name", "jdoe"), cons(element, cons("'address", ad)), cons(element, cons("'account", ac)));
+ var c = mklist(cons(element, cons("'customer", cr)));
+ var s = json.writeJSON(c);
+ assert(car(s) == "{\"customer\": {\"@name\": \"jdoe\", \"address\": {\"@city\": \"san francisco\", \"@state\": \"ca\"}, \"account\": {\"id\": \"1234\", \"@balance\": 1000}}}");
+
+ var phones = mklist("408-1234", "650-1234");
+ var l = mklist(mklist(element, "'phones", phones), mklist(element, "'lastName", "test\ttab"), mklist(attribute, "'firstName", "test1"));
+ var s2 = json.writeJSON(l);
+ assert(car(s2) == "{\"phones\": [\"408-1234\", \"650-1234\"], \"lastName\": \"test\\ttab\", \"@firstName\": \"test1\"}");
+
+ var r = json.readJSON(s2);
+ var w = json.writeJSON(r);
+ assert(car(w) == "{\"@firstName\": \"test1\", \"lastName\": \"test\\ttab\", \"phones\": [\"408-1234\", \"650-1234\"]}");
+
+ var l4 = mklist(mklist("'ns1:echoString", mklist("'@xmlns:ns1", "http://ws.apache.org/axis2/services/echo"), mklist("'text", "Hello World!")));
+ var s4 = json.writeJSON(valuesToElements(l4));
+ assert(car(s4) == "{\"ns1:echoString\": {\"@xmlns:ns1\": \"http://ws.apache.org/axis2/services/echo\", \"text\": \"Hello World!\"}}");
+
+ var r5 = elementsToValues(json.readJSON(s4));
+ var s5 = json.writeJSON(valuesToElements(r5));
+ assert(car(s5) == "{\"ns1:echoString\": {\"text\": \"Hello World!\", \"@xmlns:ns1\": \"http://ws.apache.org/axis2/services/echo\"}}");
+ return true;
+}
+
+testJSON();
+
diff --git a/sca-cpp/trunk/modules/js/util-test b/sca-cpp/trunk/modules/js/util-test
new file mode 100755
index 0000000000..ccfb377bd1
--- /dev/null
+++ b/sca-cpp/trunk/modules/js/util-test
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# 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.
+
+# Run Javascript util test cases
+here=`readlink -f $0`; here=`dirname $here`
+
+echo "Testing..."
+cat htdocs/util.js htdocs/elemutil.js htdocs/jsonutil.js json-test.js | ./js-eval 2>/dev/null 1>&2
+rc=$?
+if [ "$rc" = "0" ]; then
+ echo "OK"
+fi
+
+return $rc
diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf
index 992627596b..61dcdeeb91 100755
--- a/sca-cpp/trunk/modules/server/server-conf
+++ b/sca-cpp/trunk/modules/server/server-conf
@@ -61,6 +61,7 @@ Alias /util.js $jsprefix/htdocs/util.js
Alias /elemutil.js $jsprefix/htdocs/elemutil.js
Alias /xmlutil.js $jsprefix/htdocs/xmlutil.js
Alias /atomutil.js $jsprefix/htdocs/atomutil.js
+Alias /jsonutil.js $jsprefix/htdocs/jsonutil.js
Alias /ui.js $jsprefix/htdocs/ui.js
Alias /ui.css $jsprefix/htdocs/ui.css
Alias /scdl.js $jsprefix/htdocs/scdl.js
@@ -85,6 +86,10 @@ Require all granted
AuthType None
Require all granted
</Location>
+<Location /jsonutil.js>
+AuthType None
+Require all granted
+</Location>
<Location /ui.js>
AuthType None
Require all granted