summaryrefslogtreecommitdiffstats
path: root/sandbox/sebastien/cpp/apr-2/samples/store-gae
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/sebastien/cpp/apr-2/samples/store-gae')
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/Makefile.am44
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/app.yaml54
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/currency-converter.py29
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-backend.composite32
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-frontend.composite66
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-single.composite71
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/domain.composite71
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/fruits-catalog.py30
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/gmemcache.py45
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/index.html169
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/test/items-result.txt1
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/htpasswd.py21
-rwxr-xr-xsandbox/sebastien/cpp/apr-2/samples/store-gae/server-test59
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/shopping-cart.py82
-rwxr-xr-xsandbox/sebastien/cpp/apr-2/samples/store-gae/start21
-rwxr-xr-xsandbox/sebastien/cpp/apr-2/samples/store-gae/stop21
-rw-r--r--sandbox/sebastien/cpp/apr-2/samples/store-gae/store.py40
17 files changed, 856 insertions, 0 deletions
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/Makefile.am b/sandbox/sebastien/cpp/apr-2/samples/store-gae/Makefile.am
new file mode 100644
index 0000000000..09d5b516cf
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/Makefile.am
@@ -0,0 +1,44 @@
+# 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.
+
+if WANT_PYTHON
+if WANT_GAE
+
+dist_sample_SCRIPTS = start stop
+sampledir = $(prefix)/samples/store-gae
+
+BUILT_SOURCES = target.stamp
+target.stamp: app.yaml *.py *.composite $(top_builddir)/modules/wsgi/*.py htdocs/* $(top_builddir)/modules/js/htdocs/*
+ mkdir -p target
+ cp app.yaml *.py *.composite `ls $(top_builddir)/modules/wsgi/*.py | grep -v "\-test"` target
+ mkdir -p target/htdocs
+ cp -R htdocs/* target/htdocs
+ cp -R $(top_builddir)/modules/js/htdocs/* target/htdocs
+ touch target.stamp
+
+clean-local:
+ rm -rf target.stamp target
+
+nobase_sample_DATA = target/app.yaml target/*.py target/*.composite target/htdocs/*.html target/htdocs/*.js
+
+EXTRA_DIST = app.yaml *.composite *.py htdocs/*.html
+
+dist_noinst_SCRIPTS = server-test
+TESTS = server-test
+
+endif
+endif
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/app.yaml b/sandbox/sebastien/cpp/apr-2/samples/store-gae/app.yaml
new file mode 100644
index 0000000000..6a4e6a2fab
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/app.yaml
@@ -0,0 +1,54 @@
+# 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.
+
+application: sca-store
+version: 1
+runtime: python
+api_version: 1
+skip_files:
+- ^(.*/)?app\.yaml
+- ^(.*/)?app\.yml
+- ^(.*/)?index\.yaml
+- ^(.*/)?index\.yml
+- ^(.*/)?#.*#
+- ^(.*/)?.*~
+- ^(.*/)?.*\.py[co]
+- ^(.*/)?.*/RCS/.*
+- ^(.*/)?\..*
+- ^(.*/)?.*-test$
+- ^(.*/)?.*\.cpp$
+- ^(.*/)?.*\.o$
+- ^(.*/)?core$
+- ^(.*/)?.*\.out$
+- ^(.*/)?.*\.log$
+- ^(.*/)?Makefile.*
+- ^(.*/)?tmp/.*
+- ^(.*/)?wsgi-start
+- ^(.*/)?wsgi-stop
+
+handlers:
+- url: /(.*\.(html|png))
+ static_files: htdocs/\1
+ upload: htdocs/(.*\.(html|png))
+ secure: always
+ login: required
+
+- url: /.*
+ script: composite.py
+ secure: always
+ login: required
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/currency-converter.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/currency-converter.py
new file mode 100644
index 0000000000..2fded8f616
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/currency-converter.py
@@ -0,0 +1,29 @@
+# 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.
+
+# Currency converter implementation
+
+def convert(fr, to, amount):
+ if to == "EUR":
+ return amount * 0.70
+ return amount
+
+def symbol(currency):
+ if currency == "EUR":
+ return "E"
+ return "$"
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-backend.composite b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-backend.composite
new file mode 100644
index 0000000000..a543b9a6b5
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-backend.composite
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://store"
+ name="store-backend">
+
+ <component name="Cache">
+ <implementation.python script="gmemcache.py"/>
+ <service name="Cache">
+ <t:binding.atom uri="cache"/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-frontend.composite b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-frontend.composite
new file mode 100644
index 0000000000..e7e10e2de1
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-frontend.composite
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://store"
+ name="store-frontend">
+
+ <component name="Store">
+ <t:implementation.python script="store.py"/>
+ <service name="Widget">
+ <t:binding.http uri="store"/>
+ </service>
+ <reference name="catalog" target="Catalog"/>
+ <reference name="shoppingCart" target="ShoppingCart/Cart"/>
+ <reference name="shoppingTotal" target="ShoppingCart/Total"/>
+ </component>
+
+ <component name="Catalog">
+ <t:implementation.python script="fruits-catalog.py"/>
+ <property name="currencyCode">USD</property>
+ <service name="Catalog">
+ <t:binding.jsonrpc uri="catalog"/>
+ </service>
+ <reference name="currencyConverter" target="CurrencyConverter"/>
+ </component>
+
+ <component name="ShoppingCart">
+ <t:implementation.python script="shopping-cart.py"/>
+ <service name="Cart">
+ <t:binding.atom uri="shoppingCart"/>
+ </service>
+ <service name="Total">
+ <t:binding.jsonrpc uri="total"/>
+ </service>
+ <reference name="cache">
+ <t:binding.http uri="https://sca-store-backend.appspot.com/cache"/>
+ </reference>
+ <property name="host">localhost</property>
+ <property name="email">anonymous@example.com</property>
+ </component>
+
+ <component name="CurrencyConverter">
+ <t:implementation.python script="currency-converter.py"/>
+ <service name="CurrencyConverter">
+ <t:binding.jsonrpc uri="currencyConverter"/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-single.composite b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-single.composite
new file mode 100644
index 0000000000..4a5d53e695
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain-single.composite
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://store"
+ name="store">
+
+ <component name="Store">
+ <t:implementation.python script="store.py"/>
+ <service name="Widget">
+ <t:binding.http uri="store"/>
+ </service>
+ <reference name="catalog" target="Catalog"/>
+ <reference name="shoppingCart" target="ShoppingCart/Cart"/>
+ <reference name="shoppingTotal" target="ShoppingCart/Total"/>
+ </component>
+
+ <component name="Catalog">
+ <t:implementation.python script="fruits-catalog.py"/>
+ <property name="currencyCode">USD</property>
+ <service name="Catalog">
+ <t:binding.jsonrpc uri="catalog"/>
+ </service>
+ <reference name="currencyConverter" target="CurrencyConverter"/>
+ </component>
+
+ <component name="ShoppingCart">
+ <t:implementation.python script="shopping-cart.py"/>
+ <service name="Cart">
+ <t:binding.atom uri="shoppingCart"/>
+ </service>
+ <service name="Total">
+ <t:binding.jsonrpc uri="total"/>
+ </service>
+ <reference name="cache" target="Cache"/>
+ <property name="host">localhost</property>
+ <property name="email">anonymous@example.com</property>
+ </component>
+
+ <component name="CurrencyConverter">
+ <t:implementation.python script="currency-converter.py"/>
+ <service name="CurrencyConverter">
+ <t:binding.jsonrpc uri="currencyConverter"/>
+ </service>
+ </component>
+
+ <component name="Cache">
+ <implementation.python script="gmemcache.py"/>
+ <service name="Cache">
+ <t:binding.atom uri="cache"/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain.composite b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain.composite
new file mode 100644
index 0000000000..4a5d53e695
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/domain.composite
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://store"
+ name="store">
+
+ <component name="Store">
+ <t:implementation.python script="store.py"/>
+ <service name="Widget">
+ <t:binding.http uri="store"/>
+ </service>
+ <reference name="catalog" target="Catalog"/>
+ <reference name="shoppingCart" target="ShoppingCart/Cart"/>
+ <reference name="shoppingTotal" target="ShoppingCart/Total"/>
+ </component>
+
+ <component name="Catalog">
+ <t:implementation.python script="fruits-catalog.py"/>
+ <property name="currencyCode">USD</property>
+ <service name="Catalog">
+ <t:binding.jsonrpc uri="catalog"/>
+ </service>
+ <reference name="currencyConverter" target="CurrencyConverter"/>
+ </component>
+
+ <component name="ShoppingCart">
+ <t:implementation.python script="shopping-cart.py"/>
+ <service name="Cart">
+ <t:binding.atom uri="shoppingCart"/>
+ </service>
+ <service name="Total">
+ <t:binding.jsonrpc uri="total"/>
+ </service>
+ <reference name="cache" target="Cache"/>
+ <property name="host">localhost</property>
+ <property name="email">anonymous@example.com</property>
+ </component>
+
+ <component name="CurrencyConverter">
+ <t:implementation.python script="currency-converter.py"/>
+ <service name="CurrencyConverter">
+ <t:binding.jsonrpc uri="currencyConverter"/>
+ </service>
+ </component>
+
+ <component name="Cache">
+ <implementation.python script="gmemcache.py"/>
+ <service name="Cache">
+ <t:binding.atom uri="cache"/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/fruits-catalog.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/fruits-catalog.py
new file mode 100644
index 0000000000..4b2baca2ff
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/fruits-catalog.py
@@ -0,0 +1,30 @@
+# 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.
+
+# Catalog implementation
+
+def items(converter, currencyCode):
+ code = currencyCode.eval()
+ def convert(price):
+ return converter.convert("USD", code, price)
+ symbol = converter.symbol(code)
+ return (
+ (("'name", "Platano"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(2.99))),
+ (("'name", "Banana"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(3.55))),
+ (("'name", "Guanabana"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(1.55)))
+ )
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/gmemcache.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/gmemcache.py
new file mode 100644
index 0000000000..61f1dc3486
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/gmemcache.py
@@ -0,0 +1,45 @@
+# 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.
+
+# Google AppEngine Memcached based cache implementation
+import uuid
+from google.appengine.api import memcache
+
+# Post a new item to the cache
+def post(collection, item):
+ id = collection + (str(uuid.uuid1()),)
+ r = memcache.add(repr(id), item, 600)
+ if r == False:
+ return None
+ return id
+
+# Get items from the cache
+def get(id):
+ item = memcache.get(repr(id))
+ return item
+
+# Update an item in the cache
+def put(id, item):
+ return memcache.set(repr(id), item, 600)
+
+# Delete items from the cache
+def delete(id):
+ r = memcache.delete(repr(id))
+ if r != 2:
+ return False
+ return True
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/index.html b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/index.html
new file mode 100644
index 0000000000..a38a8a0e4f
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/index.html
@@ -0,0 +1,169 @@
+<!--
+ * 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.
+-->
+<html>
+<head>
+<title>Store</title>
+
+<script type="text/javascript" src="/component.js"></script>
+
+<script type="text/javascript">
+var store = sca.component("Store");
+var catalog = sca.defun(sca.reference(store, "catalog"), "items");
+var shoppingCart = sca.defun(sca.reference(store, "shoppingCart"), "email", "host");
+var shoppingTotal = sca.defun(sca.reference(store, "shoppingTotal"), "total");
+
+var catalogItems;
+
+function catalog_itemsResponse(items, exception) {
+ if (exception) {
+ alert(exception.message);
+ return;
+ }
+ var catalog = "";
+ for (var i=0; i<items.length; i++) {
+ var item = items[i].name + ' - ' + items[i].price;
+ catalog += '<input name="items" type="checkbox" value="' +
+ item + '">' + item + ' <br>';
+ }
+ document.getElementById('catalog').innerHTML=catalog;
+ catalogItems = items;
+}
+
+function shoppingCart_hostResponse(host, exception) {
+ if (exception) {
+ alert(exception.message);
+ return;
+ }
+ document.getElementById('host').innerHTML = host;
+}
+
+function shoppingCart_emailResponse(email, exception) {
+ if (exception) {
+ alert(exception.message);
+ return;
+ }
+ document.getElementById('email').innerHTML = email;
+}
+
+function shoppingCart_getResponse(feed) {
+ if (feed != null) {
+ var entries = feed.getElementsByTagName("entry");
+ var list = "";
+ for (var i=0; i<entries.length; i++) {
+ var content = entries[i].getElementsByTagName("content")[0];
+ var name = content.getElementsByTagName("name")[0].firstChild.nodeValue;
+ var price = content.getElementsByTagName("price")[0].firstChild.nodeValue;
+ list += name + ' - ' + price + ' <br>';
+ }
+ document.getElementById("shoppingCart").innerHTML = list;
+
+ shoppingTotal.total(shoppingTotal_totalResponse);
+ }
+}
+
+function shoppingTotal_totalResponse(total,exception) {
+ if (exception) {
+ alert(exception.message);
+ return;
+ }
+ document.getElementById('total').innerHTML = total;
+}
+
+function shoppingCart_postResponse(entry) {
+ shoppingCart.get("", shoppingCart_getResponse);
+}
+
+function addToCart() {
+ var items = document.catalogForm.items;
+ var j = 0;
+ for (var i=0; i<items.length; i++)
+ if (items[i].checked) {
+ var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><content type="application/xml">' +
+ '<item>' +
+ '<name>' + catalogItems[i].name + '</name>' +
+ '<currencyCode>' + catalogItems[i].currencyCode + '</currencyCode>' +
+ '<currencySymbol>' + catalogItems[i].currencySymbol + '</currencySymbol>' +
+ '<price>' + catalogItems[i].price + '</price>' +
+ '</item>' +
+ '</content></entry>';
+ shoppingCart.post(entry, shoppingCart_postResponse);
+ items[i].checked = false;
+ }
+}
+
+function checkoutCart() {
+ document.getElementById('store').innerHTML='<h2>' +
+ 'Thanks for Shopping With Us!</h2>'+
+ '<h2>Your Order</h2>'+
+ '<form name="orderForm">'+
+ document.getElementById('shoppingCart').innerHTML+
+ '<br>'+
+ document.getElementById('total').innerHTML+
+ '<br>'+
+ '<br>'+
+ '<input type="submit" value="Continue Shopping">'+
+ '</form>';
+ shoppingCart.del("", null);
+}
+
+function deleteCart() {
+ shoppingCart.del("", null);
+ document.getElementById('shoppingCart').innerHTML = "";
+ document.getElementById('total').innerHTML = "";
+}
+
+function init() {
+ try {
+ catalog.items(catalog_itemsResponse);
+ shoppingCart.email(shoppingCart_emailResponse);
+ shoppingCart.host(shoppingCart_hostResponse);
+ shoppingCart.get("", shoppingCart_getResponse);
+ } catch(e){
+ alert(e);
+ }
+}
+</script>
+</head>
+
+<body onload="init()">
+<h1>Store</h1>
+<p>Welcome to: <span id="host"></span>, you're signed in as: <span id="email"></span><br/><a href="/logout">Sign out</a></p>
+<div id="store">
+<h2>Catalog</h2>
+<form name="catalogForm">
+<div id="catalog" ></div>
+<br>
+<input type="button" onClick="addToCart()" value="Add to Cart">
+</form>
+<br>
+
+<h2>Your Shopping Cart</h2>
+<form name="shoppingCartForm">
+<div id="shoppingCart"></div>
+<br>
+<div id="total"></div>
+<br>
+<input type="button" onClick="checkoutCart()" value="Checkout">
+<input type="button" onClick="deleteCart()" value="Empty">
+<a href="shoppingCart/">(feed)</a>
+</form>
+</div>
+
+</body>
+</html>
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/test/items-result.txt b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/test/items-result.txt
new file mode 100644
index 0000000000..bbc07e8917
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htdocs/test/items-result.txt
@@ -0,0 +1 @@
+{"id":1,"result":[{"price":2.9900000000000002,"currencyCode":"USD","name":"Platano","currencySymbol":"$"},{"price":3.5499999999999998,"currencyCode":"USD","name":"Banana","currencySymbol":"$"},{"price":1.55,"currencyCode":"USD","name":"Guanabana","currencySymbol":"$"}]} \ No newline at end of file
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/htpasswd.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htpasswd.py
new file mode 100644
index 0000000000..75d94f58b6
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/htpasswd.py
@@ -0,0 +1,21 @@
+# 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.
+
+# Configure the user and password used for HTTP basic authentication
+user = "foo"
+passwd = "foo"
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/server-test b/sandbox/sebastien/cpp/apr-2/samples/store-gae/server-test
new file mode 100755
index 0000000000..4d42e9a5f5
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/server-test
@@ -0,0 +1,59 @@
+#!/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.
+
+echo "Testing..."
+here=`readlink -f $0`; here=`dirname $here`
+curl_prefix=`cat $here/../../modules/http/curl.prefix`
+
+# Setup
+./start 2>/dev/null
+sleep 2
+
+# Test HTTP GET (with authentication)
+mkdir -p tmp
+$curl_prefix/bin/curl -L -c tmp/cookies.txt -b tmp/cookies.txt "http://localhost:8090/_ah/login?email=test@example.com&action=Login&continue=http://localhost:8090/" 2>/dev/null >tmp/index.html
+diff tmp/index.html htdocs/index.html
+rc=$?
+
+# Test Catalog
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl -b tmp/cookies.txt http://localhost:8090/references/Store/catalog -X POST -H "Content-type: application/json-rpc" --data @../store-cpp/htdocs/test/items-request.txt >tmp/items-result.txt 2>/dev/null
+ diff tmp/items-result.txt htdocs/test/items-result.txt
+ rc=$?
+fi
+
+# Test Shopping Cart
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl -b tmp/cookies.txt http://localhost:8090/references/Store/shoppingCart -X POST -H "Content-type: application/atom+xml" --data @../store-cpp/htdocs/test/shopping-cart-entry.xml 2>/dev/null
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl -b tmp/cookies.txt http://localhost:8090/references/Store/shoppingCart >tmp/shopping-cart-feed.xml 2>/dev/null
+ grep "3.55" tmp/shopping-cart-feed.xml >/dev/null
+ rc=$?
+fi
+
+# Cleanup
+./stop
+sleep 2
+
+if [ "$rc" = "0" ]; then
+ echo "OK"
+fi
+return $rc
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/shopping-cart.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/shopping-cart.py
new file mode 100644
index 0000000000..3c3168d77b
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/shopping-cart.py
@@ -0,0 +1,82 @@
+# 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.
+
+# Shopping cart implementation
+import uuid
+import sys
+
+cartId = "1234"
+
+# Get the shopping cart from the cache
+# Return an empty cart if not found
+def getcart(id, cache):
+ cart = cache.get((id,))
+ if cart is None:
+ return ()
+ return cart
+
+# Post a new item to the cart, create a new cart if necessary
+def post(collection, item, cache, host, email):
+ id = str(uuid.uuid1())
+ cart = ((item[0], id, item[2]),) + getcart(cartId, cache)
+ cache.put((cartId,), cart)
+ return (id,)
+
+# Find an item in the cart
+def find(id, cart):
+ if cart == ():
+ return ("Item", "0", ())
+ elif id == cart[0][1]:
+ return cart[0]
+ else:
+ return find(id, cart[1:])
+
+# Get items from the cart
+def get(id, cache, host, email):
+ if id == ():
+ return ("Your Cart", cartId) + getcart(cartId, cache)
+ return find(id[0], getcart(cartId, cache))
+
+# Delete items from the cart
+def delete(id, cache, host, email):
+ if id == ():
+ return cache.delete((cartId,))
+ return True
+
+# Return the price of an item
+def price(item):
+ return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+
+# Sum the prices of a list of items
+def sum(items):
+ if items == ():
+ return 0
+ return price(items[0]) + sum(items[1:])
+
+# Return the total price of the items in the cart
+def total(cache, host, email):
+ cart = getcart(cartId, cache)
+ return sum(cart)
+
+# Return the email of the cart owner
+def email(cache, host, email_):
+ return email_.eval()
+
+# Return the host that the app is running on
+def host(cache, host_, email):
+ return host_.eval()
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/start b/sandbox/sebastien/cpp/apr-2/samples/store-gae/start
new file mode 100755
index 0000000000..3c9644e656
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/start
@@ -0,0 +1,21 @@
+#!/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.
+
+../../modules/wsgi/gae-start target 8090
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/stop b/sandbox/sebastien/cpp/apr-2/samples/store-gae/stop
new file mode 100755
index 0000000000..7c8a7e5551
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/stop
@@ -0,0 +1,21 @@
+#!/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.
+
+../../modules/wsgi/gae-stop target 8090
+
diff --git a/sandbox/sebastien/cpp/apr-2/samples/store-gae/store.py b/sandbox/sebastien/cpp/apr-2/samples/store-gae/store.py
new file mode 100644
index 0000000000..ff82f1d327
--- /dev/null
+++ b/sandbox/sebastien/cpp/apr-2/samples/store-gae/store.py
@@ -0,0 +1,40 @@
+# 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.
+
+# Store implementation
+
+def post(item, catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.post(item)
+
+def getall(catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.getall()
+
+def get(id, catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.get(id)
+
+def items(catalog, shoppingCart, shoppingTotal):
+ return catalog.items()
+
+def total(catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.total()
+
+def deleteall(catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.deleteall()
+
+def delete(id, catalog, shoppingCart, shoppingTotal):
+ return shoppingCart.delete(id)
+