summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/wsgi
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/modules/wsgi/app.yaml5
-rw-r--r--sca-cpp/trunk/modules/wsgi/atomutil.py2
-rwxr-xr-xsca-cpp/trunk/modules/wsgi/composite.py58
-rw-r--r--sca-cpp/trunk/modules/wsgi/scdl.py31
-rwxr-xr-xsca-cpp/trunk/modules/wsgi/wsgi-package30
5 files changed, 99 insertions, 27 deletions
diff --git a/sca-cpp/trunk/modules/wsgi/app.yaml b/sca-cpp/trunk/modules/wsgi/app.yaml
index 40addef28f..bc70aceced 100644
--- a/sca-cpp/trunk/modules/wsgi/app.yaml
+++ b/sca-cpp/trunk/modules/wsgi/app.yaml
@@ -41,5 +41,10 @@ skip_files:
- ^(.*/)?wsgi-stop
handlers:
+- url: /(.*\.(html|js|png))
+ static_files: htdocs/\1
+ upload: htdocs/(.*\.(html|js|png))
+
- url: /.*
script: composite.py
+
diff --git a/sca-cpp/trunk/modules/wsgi/atomutil.py b/sca-cpp/trunk/modules/wsgi/atomutil.py
index 3e3e08b27e..0ec83ca9e0 100644
--- a/sca-cpp/trunk/modules/wsgi/atomutil.py
+++ b/sca-cpp/trunk/modules/wsgi/atomutil.py
@@ -45,7 +45,7 @@ def readATOMEntry(l):
# Convert a list of values representy an ATOM entry to a value
def entryValue(e):
- v = elementsToValues((caddr(e)))
+ v = elementsToValues((caddr(e),))
return cons(car(e), (cadr(e), cdr(car(v))))
# Convert a list of strings to a list of values representing an ATOM feed
diff --git a/sca-cpp/trunk/modules/wsgi/composite.py b/sca-cpp/trunk/modules/wsgi/composite.py
index 3cccaa4ae4..0434a6b3af 100755
--- a/sca-cpp/trunk/modules/wsgi/composite.py
+++ b/sca-cpp/trunk/modules/wsgi/composite.py
@@ -21,13 +21,18 @@
from wsgiref.simple_server import make_server
from wsgiref.handlers import CGIHandler
from wsgiref.util import request_uri
+from wsgiref.util import FileWrapper
from os import environ
+import os.path
from sys import stderr, argv
from util import *
from scdl import *
from atomutil import *
from jsonutil import *
+# Cache the deployed components between requests
+comps = None
+
# Return the path of an HTTP request
def requestPath(e):
return e.get("PATH_INFO", "")
@@ -67,6 +72,9 @@ def result(r, st, h = (), b = ()):
r(car(s), list(h))
return cdr(s)
+# Send a file
+def fileresult(f):
+ return tuple(FileWrapper(open("htdocs" + f)))
# Converts the args received in a POST to a list of key value pairs
def postArgs(a):
@@ -77,21 +85,24 @@ def postArgs(a):
# WSGI application function
def application(e, r):
+ m = requestMethod(e)
+ fpath = requestPath(e)
- # Read the deployed composite
- compos = components(parse("domain-test.composite"))
- #print >> stderr, compos
+ # Debug hook
+ if fpath == "/debug":
+ return result(r, 200, (("Content-type", "text/plain"),), ("Debug",))
- # Evaluate the deployed components
- comps = evalComponents(compos)
-
- # Get the request path and method
- path = tokens(requestPath(e))
- m = requestMethod(e)
- if (isNil(path) or path == ("index.html",)) and m == "GET":
- return result(r, 200, (("Content-type", "text/html"),), ("<html><body><h1>It works!</h1></body></html>",))
+ # Serve static files
+ if m == "GET":
+ if fpath.endswith(".html"):
+ return result(r, 200, (("Content-type", "text/html"),), fileresult(fpath))
+ if fpath.endswith(".js"):
+ return result(r, 200, (("Content-type", "application/x-javascript"),), fileresult(fpath))
+ if fpath.endswith(".png"):
+ return result(r, 200, (("Content-type", "image/png"),), fileresult(fpath))
# Find the requested component
+ path = tokens(fpath)
uc = uriToComponent(path, comps)
uri = car(uc)
if uri == None:
@@ -100,7 +111,7 @@ def application(e, r):
# Call the requested component function
id = path[len(uri):]
- if (m == "GET"):
+ if m == "GET":
v = comp("get", id)
# Write returned content-type / content pair
@@ -148,21 +159,30 @@ def application(e, r):
return result(r, 404)
return result(r, 200)
- # TODO implement POST and PUT methods
return result(r, 500)
# Return the WSGI server type
def serverType(e):
return e.get("SERVER_SOFTWARE", "")
-# Run the WSGI application
-if __name__ == "__main__":
+def main():
+ # Read the deployed composite and evaluate the configured components
+ global comps
+ if comps == None:
+ domain = "domain.composite" if os.path.exists("domain.composite") else "domain-test.composite"
+ comps = evalComponents(components(parse(domain)))
+
+ # Handle the WSGI request with the WSGI runtime
st = serverType(environ)
- if st == "":
- make_server("", int(argv[1]), application).serve_forever()
- elif st == "Development/1.0":
+ if st.find("App Engine") != -1 or st.find("Development") != -1:
from google.appengine.ext.webapp.util import run_wsgi_app
run_wsgi_app(application)
- else:
+ elif st != "":
CGIHandler().run(application)
+ else:
+ make_server("", int(argv[1]), application).serve_forever()
+
+# Run the WSGI application
+if __name__ == "__main__":
+ main()
diff --git a/sca-cpp/trunk/modules/wsgi/scdl.py b/sca-cpp/trunk/modules/wsgi/scdl.py
index 056523fb23..2e57c77377 100644
--- a/sca-cpp/trunk/modules/wsgi/scdl.py
+++ b/sca-cpp/trunk/modules/wsgi/scdl.py
@@ -33,27 +33,31 @@ def elt(e):
def att(e):
return elt(e).attrib
+def text(e):
+ return elt(e).text
+
def match(e, ev, tag):
return evt(e) == ev and elt(e).tag.find("}" + tag) != -1
# Make a callable component
class component:
- def __init__(self, name, impl, svcs, refs):
+ def __init__(self, name, impl, svcs, refs, props):
self.name = name
self.impl = impl
self.mod = None
self.svcs = svcs
self.refs = refs
+ self.props = props
self.proxies = ()
def __call__(self, func, *args):
return self.mod.__getattribute__(func)(*(args + self.proxies))
def __repr__(self):
- return repr((self.name, self.impl, self.mod, self.svcs, self.refs, self.proxies))
+ return repr((self.name, self.impl, self.mod, self.svcs, self.refs, self.props, self.proxies))
-def mkcomponent(name, impl, svcs, refs):
- return component(name, impl, svcs, refs)
+def mkcomponent(name, impl, svcs, refs, props):
+ return component(name, impl, svcs, refs, props)
# Return the Python module name of a component implementation
def implementation(e):
@@ -81,9 +85,17 @@ def references(e):
if match(car(e), "start", "reference") == False:
return references(cdr(e))
if "target" in att(car(e)):
- return (att(car(e))["target"],) + references(cdr(e))
+ return cons(att(car(e))["target"], references(cdr(e)))
return cons(binding(e), references(cdr(e)))
+# Return the list of properties under a SCDL component element
+def properties(e):
+ if len(e) == 0 or match(car(e), "end", "component") == True:
+ return ()
+ if match(car(e), "start", "property") == False:
+ return properties(cdr(e))
+ return cons(text(car(e)), properties(cdr(e)))
+
# Return the list of services under a SCDL component element
def services(e):
if len(e) == 0 or match(car(e), "end", "component") == True:
@@ -103,7 +115,7 @@ def components(e):
if match(car(e), "start", "component") == False:
return components(cdr(e))
n = name(e)
- return cons(mkcomponent(n, implementation(e), cons(("components", n), services(e)), references(e)), components(cdr(e)))
+ return cons(mkcomponent(n, implementation(e), cons(("components", n), services(e)), references(e), properties(e)), components(cdr(e)))
# Find a component with a given name
def nameToComponent(name, comps):
@@ -133,7 +145,12 @@ def uriToComponent(u, comps):
# Evaluate a component, resolve its implementation and references
def evalComponent(comp, comps):
comp.mod = __import__(comp.impl)
- comp.proxies = tuple(map(lambda r: nameToComponent(r, comps), comp.refs))
+
+ # Make a list of proxy lambda functions for the component references and properties
+ # A reference proxy is the callable lambda function of the component wired to the reference
+ # A property proxy is a lambda function that returns the value of the property
+ comp.proxies = tuple(map(lambda r: nameToComponent(r, comps), comp.refs)) + tuple(map(lambda v: lambda: v, comp.props))
+
return comp
# Evaluate a list of components
diff --git a/sca-cpp/trunk/modules/wsgi/wsgi-package b/sca-cpp/trunk/modules/wsgi/wsgi-package
new file mode 100755
index 0000000000..28756f9494
--- /dev/null
+++ b/sca-cpp/trunk/modules/wsgi/wsgi-package
@@ -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.
+
+# Package a WSGI app for upload
+here=`readlink -f $0`; here=`dirname $here`
+pwd=`pwd`
+root=`readlink -f $pwd`
+
+rm -rf target
+mkdir -p target
+cd target
+ls $here/*.py | grep -v "\-test.py" | xargs -i -t ln -s -f {}
+ls $root | grep -v "target" | xargs -i -t ln -s -f $root/{}
+