diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-06-05 05:38:43 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-06-05 05:38:43 +0000 |
commit | 69c6e0618ad4f18d18771ef91aacbb5c5a68f3a2 (patch) | |
tree | 2456aa85d86125726127b0d4ab022f68d2fc710b | |
parent | f052ca9d9dc273dc0f625c9a6ec6eb38d6bc0f3a (diff) |
Add RSS support to the WSGI integration module.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@951655 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | sca-cpp/trunk/modules/rss/rss-test.cpp | 30 | ||||
-rwxr-xr-x | sca-cpp/trunk/modules/wsgi/atom-test.py | 19 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/wsgi/atomutil.py | 23 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/wsgi/httputil.py | 58 | ||||
-rwxr-xr-x | sca-cpp/trunk/modules/wsgi/rss-test.py | 170 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/wsgi/rssutil.py | 119 | ||||
-rwxr-xr-x | sca-cpp/trunk/modules/wsgi/util-test | 4 |
7 files changed, 377 insertions, 46 deletions
diff --git a/sca-cpp/trunk/modules/rss/rss-test.cpp b/sca-cpp/trunk/modules/rss/rss-test.cpp index 3168e1f474..9bfd620835 100644 --- a/sca-cpp/trunk/modules/rss/rss-test.cpp +++ b/sca-cpp/trunk/modules/rss/rss-test.cpp @@ -41,9 +41,9 @@ string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<title>fruit</title>" "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" "<description>" - "<fruit>" + "<item>" "<name>Apple</name><price>$2.99</price>" - "</fruit>" + "</item>" "</description>" "</item>\n"); @@ -56,10 +56,10 @@ string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" string incompleteEntry("<item>" "<title>fruit</title><description>" - "<fruit xmlns=\"http://services/\">" + "<Item xmlns=\"http://services/\">" "<name xmlns=\"\">Orange</name>" "<price xmlns=\"\">3.55</price>" - "</fruit>" + "</Item>" "</description>" "</item>"); @@ -68,16 +68,16 @@ string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<title>fruit</title>" "<link></link>" "<description>" - "<fruit xmlns=\"http://services/\">" + "<Item xmlns=\"http://services/\">" "<name xmlns=\"\">Orange</name>" "<price xmlns=\"\">3.55</price>" - "</fruit>" + "</Item>" "</description>" "</item>\n"); bool testEntry() { { - const list<value> i = list<value>() + element + value("fruit") + const list<value> i = list<value>() + element + value("item") + value(list<value>() + element + value("name") + value(string("Apple"))) + value(list<value>() + element + value("price") + value(string("$2.99"))); const list<value> a = mklist<value>(string("fruit"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); @@ -131,18 +131,18 @@ string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<title>fruit</title>" "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" "<description>" - "<fruit>" + "<item>" "<name>Apple</name><price>$2.99</price>" - "</fruit>" + "</item>" "</description>" "</item>" "<item>" "<title>fruit</title>" "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>" "<description>" - "<fruit>" + "<item>" "<name>Orange</name><price>$3.55</price>" - "</fruit>" + "</item>" "</description>" "</item>" "</channel>" @@ -163,11 +163,11 @@ bool testFeed() { { const list<value> i = list<value>() + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - + (list<value>() + element + "fruit" + + (list<value>() + element + "item" + (list<value>() + element + "name" + "Apple") + (list<value>() + element + "price" + "$2.99"))) + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - + (list<value>() + element + "fruit" + + (list<value>() + element + "item" + (list<value>() + element + "name" + "Orange") + (list<value>() + element + "price" + "$3.55"))); const list<value> a = cons<value>("Feed", cons<value>("1234", i)); @@ -178,11 +178,11 @@ bool testFeed() { { const list<value> i = list<value>() + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - + valueToElement(list<value>() + "fruit" + + valueToElement(list<value>() + "item" + (list<value>() + "name" + "Apple") + (list<value>() + "price" + "$2.99"))) + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - + valueToElement(list<value>() + "fruit" + + valueToElement(list<value>() + "item" + (list<value>() + "name" + "Orange") + (list<value>() + "price" + "$3.55"))); const list<value> a = cons<value>("Feed", cons<value>("1234", i)); diff --git a/sca-cpp/trunk/modules/wsgi/atom-test.py b/sca-cpp/trunk/modules/wsgi/atom-test.py index 61435bf438..81a6106519 100755 --- a/sca-cpp/trunk/modules/wsgi/atom-test.py +++ b/sca-cpp/trunk/modules/wsgi/atom-test.py @@ -35,6 +35,17 @@ itemEntry = \ "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\" />" \ "</entry>\n" +textEntry = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" \ + "<title type=\"text\">item</title>" \ + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" \ + "<content type=\"text\">" \ + "Apple" \ + "</content>" \ + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\" />" \ + "</entry>\n" + incompleteEntry = \ "<entry xmlns=\"http://www.w3.org/2005/Atom\">" \ "<title>item</title><content type=\"text/xml\">" \ @@ -68,9 +79,13 @@ def testEntry(): s2 = writeATOMEntry(a2) assert car(s2) == itemEntry - a3 = readATOMEntry((incompleteEntry,)) + a3 = readATOMEntry((textEntry,)) s3 = writeATOMEntry(a3) - assert car(s3) == completedEntry + assert car(s3) == textEntry + + a4 = readATOMEntry((incompleteEntry,)) + s4 = writeATOMEntry(a4) + assert car(s4) == completedEntry return True emptyFeed = \ diff --git a/sca-cpp/trunk/modules/wsgi/atomutil.py b/sca-cpp/trunk/modules/wsgi/atomutil.py index 0ec83ca9e0..6c0a7c9a81 100644 --- a/sca-cpp/trunk/modules/wsgi/atomutil.py +++ b/sca-cpp/trunk/modules/wsgi/atomutil.py @@ -28,7 +28,7 @@ def entryElementsToValues(e): li = filter(selector((element, "'id")), e) i = "" if isNil(li) else elementValue(car(li)) lc = filter(selector((element, "'content")), e) - return (t, i, cadr(elementChildren(car(lc)))) + return (t, i, elementValue(car(lc))) # Convert a list of elements to a list of values representing ATOM entries def entriesElementsToValues(e): @@ -48,6 +48,14 @@ def entryValue(e): v = elementsToValues((caddr(e),)) return cons(car(e), (cadr(e), cdr(car(v)))) +# Return true if a list of strings represents an ATOM feed +def isATOMFeed(l): + if isNil(l): + return False + if car(l)[0:5] != "<?xml": + return False + return contains(car(l), "<feed") + # Convert a list of strings to a list of values representing an ATOM feed def readATOMFeed(l): f = readXML(l) @@ -60,12 +68,21 @@ def readATOMFeed(l): return (elementValue(car(t)), elementValue(car(i))) return cons(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e))) +# Convert an ATOM feed containing elements to an ATOM feed containing values +def feedValuesLoop(e): + if (isNil(e)): + return e + return cons(entryValue(car(e)), feedValuesLoop(cdr(e))) + +def feedValues(e): + return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e)))) + # Convert a list of values representy an ATOM entry to a list of elements def entryElement(l): return (element, "'entry", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"), (element, "'title", (attribute, "'type", "text"), car(l)), (element, "'id", cadr(l)), - (element, "'content", (attribute, "'type", "application/xml"), caddr(l)), + (element, "'content", (attribute, "'type", ("application/xml" if isList(caddr(l)) else "text")), caddr(l)), (element, "'link", (attribute, "'href", cadr(l)))) # Convert a list of values representing ATOM entries to a list of elements @@ -85,7 +102,7 @@ def writeATOMFeed(l): (element, "'id", cadr(l))) if isNil(cddr(l)): return writeXML((f,), True) - fe = f + entriesElements(cddr(l)) + fe = append(f, entriesElements(cddr(l))) return writeXML((fe,), True) # Convert an ATOM entry containing a value to an ATOM entry containing an item element diff --git a/sca-cpp/trunk/modules/wsgi/httputil.py b/sca-cpp/trunk/modules/wsgi/httputil.py index 77d19eabe2..3d0c3350ef 100644 --- a/sca-cpp/trunk/modules/wsgi/httputil.py +++ b/sca-cpp/trunk/modules/wsgi/httputil.py @@ -29,41 +29,27 @@ from util import * from atomutil import * from jsonutil import * +# JSON request id id = 1 # Make a callable HTTP client class client: - def __init__(self, uri): - self.uri = urlparse(uri) + def __init__(self, url): + self.url = urlparse(url) def __call__(self, func, *args): - # Connect to the configured URI - print >> stderr, "Client POST", self.uri.geturl() - c = None - headers = {"Content-type": "application/json-rpc"} - if self.uri.scheme == "https": + # Connect to the configured URL + print >> stderr, "Client POST", self.url.geturl() + c, headers = connect(self.url) - # With HTTPS, use a cerficate or HTTP basic authentication - if os.path.exists("server.key"): - c = HTTPSConnection(self.uri.hostname, 443 if self.uri.port == None else self.uri.port, "server.key", "server.crt") - else: - c = HTTPSConnection(self.uri.hostname, 443 if self.uri.port == None else self.uri.port) - - # For HTTP basic authentication the user and password are - # provided by htpasswd.py - import htpasswd - auth = 'Basic ' + b64encode(htpasswd.user + ':' + htpasswd.passwd) - headers["Authorization"] = auth - else: - c = HTTPConnection(self.uri.hostname, 80 if self.uri.port == None else self.uri.port) - - # POST the JSON-RPC request + # POST a JSON-RPC request global id req = StringIO() writeStrings(jsonRequest(id, func, args), req) id = id + 1 - c.request("POST", self.uri.path, req.getvalue(), headers) + headers["Content-type"] = "application/json-rpc" + c.request("POST", self.url.path, req.getvalue(), headers) res = c.getresponse() print >> stderr, "Client status", res.status if res.status != 200: @@ -71,8 +57,28 @@ class client: return jsonResultValue((res.read(),)) def __repr__(self): - return repr((self.uri,)) + return repr((self.url,)) + +def mkclient(url): + return client(url) + +# Connect to a URL, return a connection and any authorization headers +def connect(url): + if url.scheme == "https": + + # With HTTPS, use a cerficate or HTTP basic authentication + if os.path.exists("server.key"): + c = HTTPSConnection(url.hostname, 443 if url.port == None else url.port, "server.key", "server.crt") + return c, {} + else: + c = HTTPSConnection(url.hostname, 443 if url.port == None else url.port) -def mkclient(uri): - return client(uri) + # For HTTP basic authentication the user and password are + # provided by htpasswd.py + import htpasswd + auth = 'Basic ' + b64encode(htpasswd.user + ':' + htpasswd.passwd) + return c, {"Authorization": auth} + else: + c = HTTPConnection(url.hostname, 80 if url.port == None else url.port) + return c, {} diff --git a/sca-cpp/trunk/modules/wsgi/rss-test.py b/sca-cpp/trunk/modules/wsgi/rss-test.py new file mode 100755 index 0000000000..e8a094b7d8 --- /dev/null +++ b/sca-cpp/trunk/modules/wsgi/rss-test.py @@ -0,0 +1,170 @@ +#!/usr/bin/python +# 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 RSS data conversion functions + +import unittest +from elemutil import * +from rssutil import * + +itemEntry = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<item>" \ + "<title>fruit</title>" \ + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" \ + "<description>" \ + "<item>" \ + "<name>Apple</name><price>$2.99</price>" \ + "</item>" \ + "</description>" \ + "</item>\n" + +textEntry = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<item>" \ + "<title>fruit</title>" \ + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" \ + "<description>" \ + "Apple" \ + "</description>" \ + "</item>\n" + +incompleteEntry = \ + "<item>" \ + "<title>fruit</title><description>" \ + "<fruit xmlns=\"http://services/\">" \ + "<name xmlns=\"\">Orange</name>" \ + "<price xmlns=\"\">3.55</price>" \ + "</fruit>" \ + "</description>" \ + "</item>" + +completedEntry = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<item>" \ + "<title>fruit</title>" \ + "<link />" \ + "<description>" \ + "<fruit xmlns=\"http://services/\">" \ + "<name xmlns=\"\">Orange</name>" \ + "<price xmlns=\"\">3.55</price>" \ + "</fruit>" \ + "</description>" \ + "</item>\n" + +def testEntry(): + i = (element, "'item", (element, "'name", "Apple"), (element, "'price", "$2.99")) + a = ("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b", i) + s = writeRSSEntry(a); + assert car(s) == itemEntry + + a2 = readRSSEntry((itemEntry,)) + s2 = writeRSSEntry(a2) + assert car(s2) == itemEntry + + a3 = readRSSEntry((textEntry,)) + s3 = writeRSSEntry(a3) + assert car(s3) == textEntry + + a4 = readRSSEntry((incompleteEntry,)) + s4 = writeRSSEntry(a4) + assert car(s4) == completedEntry + return True + +emptyFeed = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<rss version=\"2.0\">" \ + "<channel>" \ + "<title>Feed</title>" \ + "<link>1234</link>" \ + "<description>Feed</description>" \ + "</channel>" \ + "</rss>\n" + +itemFeed = \ + "<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n" \ + "<rss version=\"2.0\">" \ + "<channel>" \ + "<title>Feed</title>" \ + "<link>1234</link>" \ + "<description>Feed</description>" \ + "<item>" \ + "<title>fruit</title>" \ + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" \ + "<description>" \ + "<item>" \ + "<name>Apple</name><price>$2.99</price>" \ + "</item>" \ + "</description>" \ + "</item>" \ + "<item>" \ + "<title>fruit</title>" \ + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>" \ + "<description>" \ + "<item>" \ + "<name>Orange</name><price>$3.55</price>" \ + "</item>" \ + "</description>" \ + "</item>" \ + "</channel>" \ + "</rss>\n" + +def testFeed(): + s = writeRSSFeed(("Feed", "1234")) + assert car(s) == emptyFeed + + a2 = readRSSFeed((emptyFeed,)) + s2 = writeRSSFeed(a2) + assert car(s2) == emptyFeed + + i3 = (("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b", + (element, "'item", (element, "'name", "Apple"), (element, "'price", "$2.99"))), + ("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c", + (element, "'item", (element, "'name", "Orange"), (element, "'price", "$3.55")))) + a3 = cons("Feed", cons("1234", i3)) + s3 = writeRSSFeed(a3) + assert car(s3) == itemFeed + + i4 = (("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b", + valueToElement(("'item", ("'name", "Apple"), ("'price", "$2.99")))), + ("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c", + valueToElement(("'item", ("'name", "Orange"), ("'price", "$3.55"))))) + a4 = cons("Feed", cons("1234", i4)) + s4 = writeRSSFeed(a4) + assert car(s4) == itemFeed + + a5 = readRSSFeed((itemFeed,)); + s5 = writeRSSFeed(a5); + assert car(s5) == itemFeed + + i6 = (("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b", + (("'name", "Apple"), ("'price", "$2.99"))), + ("fruit", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c", + (("'name", "Orange"), ("'price", "$3.55")))) + a6 = cons("Feed", cons("1234", i6)) + s6 = writeRSSFeed(feedValuesToElements(a6)) + assert car(s6) == itemFeed + + return True + +if __name__ == "__main__": + print "Testing..." + testEntry() + testFeed() + print "OK" + diff --git a/sca-cpp/trunk/modules/wsgi/rssutil.py b/sca-cpp/trunk/modules/wsgi/rssutil.py new file mode 100644 index 0000000000..4f060d2321 --- /dev/null +++ b/sca-cpp/trunk/modules/wsgi/rssutil.py @@ -0,0 +1,119 @@ +# 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. + +# RSS data conversion functions + +from util import * +from elemutil import * +from xmlutil import * + +# Convert a list of elements to a list of values representing an RSS entry +def entryElementsToValues(e): + lt = filter(selector((element, "'title")), e) + t = "" if isNil(lt) else elementValue(car(lt)) + li = filter(selector((element, "'link")), e) + i = "" if isNil(li) else elementValue(car(li)) + lc = filter(selector((element, "'description")), e) + return (t, i, elementValue(car(lc))) + +# Convert a list of elements to a list of values representing RSS entries +def entriesElementsToValues(e): + if isNil(e): + return e + return cons(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e))) + +# Convert a list of strings to a list of values representing an RSS entry +def readRSSEntry(l): + e = readXML(l) + if isNil(e): + return () + return entryElementsToValues(car(e)) + +# Convert a list of values representy an RSS entry to a value +def entryValue(e): + v = elementsToValues((caddr(e),)) + return cons(car(e), (cadr(e), cdr(car(v)))) + +# Return true if a list of strings represents an RSS feed +def isRSSFeed(l): + if isNil(l): + return False + if car(l)[0:5] != "<?xml": + return False + return contains(car(l), "<rss") + +# Convert a list of strings to a list of values representing an RSS feed +def readRSSFeed(l): + f = readXML(l) + if isNil(f): + return () + c = filter(selector((element, "'channel")), car(f)) + t = filter(selector((element, "'title")), car(c)) + i = filter(selector((element, "'link")), car(c)) + e = filter(selector((element, "'item")), car(c)) + if isNil(e): + return (elementValue(car(t)), elementValue(car(i))) + return cons(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e))) + +# Convert an RSS feed containing elements to an RSS feed containing values +def feedValuesLoop(e): + if (isNil(e)): + return e + return cons(entryValue(car(e)), feedValuesLoop(cdr(e))) + +def feedValues(e): + return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e)))) + +# Convert a list of values representy an RSS entry to a list of elements +def entryElement(l): + return (element, "'item", + (element, "'title", car(l)), + (element, "'link", cadr(l)), + (element, "'description", caddr(l))) + +# Convert a list of values representing RSS entries to a list of elements +def entriesElements(l): + if isNil(l): + return l + return cons(entryElement(car(l)), entriesElements(cdr(l))) + +# Convert a list of values representing an RSS entry to an RSS entry +def writeRSSEntry(l): + return writeXML((entryElement(l),), True) + +# Convert a list of values representing an RSS feed to an RSS feed +def writeRSSFeed(l): + c = ((element, "'title", car(l)), + (element, "'link", cadr(l)), + (element, "'description", car(l))) + ce = c if isNil(cddr(l)) else append(c, entriesElements(cddr(l))) + fe = (element, "'rss", (attribute, "'version", "2.0"), append((element, "'channel"), ce)) + return writeXML((fe,), True) + +# Convert an RSS entry containing a value to an RSS entry containing an item element +def entryValuesToElements(v): + return cons(car(v), cons(cadr(v), valuesToElements((cons("'item", caddr(v)),)))) + +# Convert an RSS feed containing values to an RSS feed containing elements +def feedValuesToElementsLoop(v): + if isNil(v): + return v + return cons(entryValuesToElements(car(v)), feedValuesToElementsLoop(cdr(v))) + +def feedValuesToElements(v): + return cons(car(v), cons(cadr(v), feedValuesToElementsLoop(cddr(v)))) + diff --git a/sca-cpp/trunk/modules/wsgi/util-test b/sca-cpp/trunk/modules/wsgi/util-test index cb4e2f6c8a..aa8725a200 100755 --- a/sca-cpp/trunk/modules/wsgi/util-test +++ b/sca-cpp/trunk/modules/wsgi/util-test @@ -32,6 +32,10 @@ if [ "$rc" = "0" ]; then rc=$? fi if [ "$rc" = "0" ]; then + $python_prefix/bin/python rss-test.py + rc=$? +fi +if [ "$rc" = "0" ]; then $python_prefix/bin/python json-test.py rc=$? fi |