You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2010/07/06 11:06:08 UTC

svn commit: r960847 - in /tuscany/sca-cpp/trunk: ./ modules/http/ modules/server/ samples/ samples/store-python/ samples/store-vhost/ samples/store-vhost/htdocs/ samples/store-vhost/htdocs/domains/ samples/store-vhost/htdocs/domains/jane/ samples/store...

Author: jsdelfino
Date: Tue Jul  6 09:06:07 2010
New Revision: 960847

URL: http://svn.apache.org/viewvc?rev=960847&view=rev
Log:
Add support for HTTPD mass dynamic virtual hosting. Components can now be deployed, resolved, wired and invoked within a virtual host.

Added:
    tuscany/sca-cpp/trunk/samples/store-vhost/
    tuscany/sca-cpp/trunk/samples/store-vhost/Makefile.am
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/currency-converter.py
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/fruits-catalog.py
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html
    tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/index.html
    tuscany/sca-cpp/trunk/samples/store-vhost/server-test   (contents, props changed)
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/shopping-cart.py
    tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start   (contents, props changed)
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/start   (contents, props changed)
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/stop   (contents, props changed)
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/store.composite
    tuscany/sca-cpp/trunk/samples/store-vhost/store.py
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start   (contents, props changed)
      - copied, changed from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
Modified:
    tuscany/sca-cpp/trunk/configure.ac
    tuscany/sca-cpp/trunk/modules/http/httpd-conf
    tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf
    tuscany/sca-cpp/trunk/modules/http/httpd.hpp
    tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp
    tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp
    tuscany/sca-cpp/trunk/modules/server/server-conf
    tuscany/sca-cpp/trunk/samples/Makefile.am
    tuscany/sca-cpp/trunk/samples/store-python/Makefile.am

Modified: tuscany/sca-cpp/trunk/configure.ac
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/configure.ac?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/configure.ac (original)
+++ tuscany/sca-cpp/trunk/configure.ac Tue Jul  6 09:06:07 2010
@@ -859,6 +859,7 @@ AC_CONFIG_FILES([Makefile
                  samples/store-gae/Makefile
                  samples/store-sql/Makefile
                  samples/store-nosql/Makefile
+                 samples/store-vhost/Makefile
                  doc/Makefile
                  doc/Doxyfile
                  ubuntu/Makefile

Modified: tuscany/sca-cpp/trunk/modules/http/httpd-conf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/httpd-conf?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/httpd-conf (original)
+++ tuscany/sca-cpp/trunk/modules/http/httpd-conf Tue Jul  6 09:06:07 2010
@@ -30,6 +30,13 @@ htdocs=`readlink -f $4`
 user=`id -un`
 group=`id -gn`
 modules_prefix=`cat $here/httpd-modules.prefix`
+if [ "$5" = "vhost" ]; then
+    vhost="VirtualDocumentRoot $htdocs/domains/%1/"
+    maxr="MaxRequestsPerChild 1"
+else
+    vhost="#VirtualDocumentRoot $htdocs/domains/%1/"
+    maxr="#MaxRequestsPerChild 1"
+fi
 
 mkdir -p $root
 mkdir -p $root/logs
@@ -39,8 +46,6 @@ cat >$root/conf/httpd.conf <<EOF
 
 # Set server name
 ServerName http://$host:$pport
-UseCanonicalName On
-UseCanonicalPhysicalPort off
 PidFile $root/logs/httpd.pid
 
 # Minimal set of modules
@@ -68,6 +73,7 @@ LoadModule setenvif_module ${modules_pre
 <IfModule !log_config_module>
 LoadModule log_config_module ${modules_prefix}/modules/mod_log_config.so
 </IfModule>
+LoadModule vhost_alias_module ${modules_prefix}/modules/mod_vhost_alias.so
 
 # Basic security precautions
 User $user
@@ -121,7 +127,15 @@ Allow from all
 Listen $port
 <VirtualHost _default_:$port>
 ServerName http://$host:$pport
+UseCanonicalName Off
+UseCanonicalPhysicalPort Off
+
+# Setup mass dynamic virtual hosting
+$vhost
 </VirtualHost>
 
+# Isolate dynamic virtual hosts
+$maxr
+
 EOF
 

Modified: tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf (original)
+++ tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf Tue Jul  6 09:06:07 2010
@@ -55,8 +55,8 @@ SSLRandomSeed connect builtin
 Listen $sslport
 <VirtualHost _default_:$sslport>
 ServerName https://$host:$sslpport
-UseCanonicalName On
-UseCanonicalPhysicalPort off
+UseCanonicalName Off
+UseCanonicalPhysicalPort Off
 
 # Enable SSL
 SSLEngine on

Modified: tuscany/sca-cpp/trunk/modules/http/httpd.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/httpd.hpp?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/httpd.hpp (original)
+++ tuscany/sca-cpp/trunk/modules/http/httpd.hpp Tue Jul  6 09:06:07 2010
@@ -75,6 +75,31 @@ template<typename C> C& serverConf(const
 
 
 /**
+ * Return the name of a server.
+ */
+const string serverName(const server_rec* s) {
+    ostringstream n;
+    n << (s->server_scheme != NULL? s->server_scheme : "http") << "://"
+        << (s->server_hostname != NULL? s->server_hostname : "localhost") << ":"
+        << (s->port != 0? s->port : 80)
+        << (s->path != NULL? string(s->path, s->pathlen) : "");
+    return str(n);
+}
+
+/**
+ * Determine the name of a server from an HTTP request.
+ */
+const string serverName(request_rec* r) {
+    ostringstream n;
+    const char* hn = ap_get_server_name(r);
+    n << (r->server->server_scheme != NULL? r->server->server_scheme : "http") << "://"
+        << (hn != NULL? hn : (r->server->server_hostname != NULL? r->server->server_hostname : "localhost")) << ":"
+        << (r->server->port != 0? r->server->port : 80)
+        << (r->server->path != NULL? string(r->server->path, r->server->pathlen) : "");
+    return str(n);
+}
+
+/**
  * Return the content type of a request.
  */
 const char* optional(const char* s) {
@@ -295,7 +320,7 @@ const bool redirectFilters(ap_filter_t* 
 }
 
 /**
- * Create an HTTPD redirect request.
+ * Create an HTTPD internal redirect request.
  * Similar to httpd/modules/http/http_request.c::internal_internal_redirect.
  */
 extern "C" {
@@ -388,7 +413,7 @@ const int internalRedirect(request_rec* 
 }
 
 /**
- * Create and process an HTTPD redirect request.
+ * Create and process an HTTPD internal redirect request.
  */
 const int internalRedirect(const string& uri, request_rec* r) {
     const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r);

Modified: tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp (original)
+++ tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp Tue Jul  6 09:06:07 2010
@@ -53,14 +53,16 @@ namespace modeval {
  */
 class ServerConf {
 public:
-    ServerConf(server_rec* s) : s(s), wiringServerName(""), contributionPath(""), compositeName(""), ca(""), cert(""), key("") {
+    ServerConf(server_rec* s) : server(s), wiringServerName(""), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(""), cert(""), key("") {
     }
 
-    const server_rec* s;
+    server_rec* server;
     lambda<value(const list<value>&)> lifecycle;
     string wiringServerName;
     string contributionPath;
     string compositeName;
+    string virtualHostContributionPath;
+    string virtualHostCompositeName;
     string ca;
     string cert;
     string key;
@@ -69,6 +71,13 @@ public:
 };
 
 /**
+ * Return true if a server contains a composite configuration.
+ */
+const bool hasCompositeConf(const ServerConf& sc) {
+    return sc.contributionPath != "" && sc.compositeName != "";
+}
+
+/**
  * Convert a result represented as a content + failure pair to a
  * failable monad.
  */
@@ -241,6 +250,19 @@ int translate(request_rec *r) {
 }
 
 /**
+ * Convert a list of component references to a list of HTTP proxy lambdas.
+ */
+const value mkrefProxy(const value& ref, const string& base, const string& ca, const string& cert, const string& key) {
+    return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)), ca, cert, key));
+}
+
+const list<value> refProxies(const list<value>& refs, const string& base, const string& ca, const string& cert, const string& key) {
+    if (isNil(refs))
+        return refs;
+    return cons(mkrefProxy(car(refs), base, ca, cert, key), refProxies(cdr(refs), base, ca, cert, key));
+}
+
+/**
  * Store current HTTP request for access from property lambda functions.
  */
 #ifdef WANT_THREADS
@@ -248,63 +270,18 @@ __thread
 #endif
 const request_rec* currentRequest = NULL;
 
-class scoped_request {
+class ScopedRequest {
 public:
-    scoped_request(const request_rec* r) {
+    ScopedRequest(const request_rec* r) {
         currentRequest = r;
     }
 
-    ~scoped_request() {
+    ~ScopedRequest() {
         currentRequest = NULL;
     }
 };
 
 /**
- * HTTP request handler.
- */
-int handler(request_rec *r) {
-    if(strcmp(r->handler, "mod_tuscany_eval"))
-        return DECLINED;
-    gc_scoped_pool pool(r->pool);
-    scoped_request sr(r);
-    httpdDebugRequest(r, "modeval::handler::input");
-
-    // Get the component implementation lambda
-    const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval);
-    const list<value> path(pathValues(r->uri));
-    const list<value> impl(assoctree<value>(cadr(path), sc.implTree));
-    if (isNil(impl))
-        return httpd::reportStatus(mkfailure<int>(string("Couldn't find component implementation")));
-
-    // Handle HTTP method
-    const lambda<value(const list<value>&)> l(cadr<value>(impl));
-    if (r->header_only)
-         return OK;
-    if(r->method_number == M_GET)
-        return httpd::reportStatus(get(r, l));
-    if(r->method_number == M_POST)
-        return httpd::reportStatus(post(r, l));
-    if(r->method_number == M_PUT)
-        return httpd::reportStatus(put(r, l));
-    if(r->method_number == M_DELETE)
-        return httpd::reportStatus(del(r, l));
-    return HTTP_NOT_IMPLEMENTED;
-}
-
-/**
- * Convert a list of component references to a list of HTTP proxy lambdas.
- */
-const value mkrefProxy(const value& ref, const string& base, const string& ca, const string& cert, const string& key) {
-    return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)), ca, cert, key));
-}
-
-const list<value> refProxies(const list<value>& refs, const string& base, const string& ca, const string& cert, const string& key) {
-    if (isNil(refs))
-        return refs;
-    return cons(mkrefProxy(car(refs), base, ca, cert, key), refProxies(cdr(refs), base, ca, cert, key));
-}
-
-/**
  * Convert a list of component properties to a list of lambda functions that just return
  * the property value. The user and email properties are configured with the values
  * from the HTTP request, if any.
@@ -374,20 +351,14 @@ struct implementationFailure {
     }
 };
 
-const value evalComponent(ServerConf& sc, server_rec& server, const value& comp) {
+const value evalComponent(ServerConf& sc, const value& comp) {
     extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle);
 
     const value impl = scdl::implementation(comp);
 
     // Convert component references to configured proxy lambdas
     ostringstream base;
-    if (sc.wiringServerName == "")
-        base << (server.server_scheme == NULL? "http" : server.server_scheme)
-            << "://" << (server.server_hostname == NULL? "localhost" : server.server_hostname)
-            << ":" << (server.port == 0? 80 : server.port)
-            << "/references/" << string(scdl::name(comp)) << "/";
-    else
-        base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/";
+    base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/";
     const list<value> rpx(refProxies(scdl::references(comp), str(base), sc.ca, sc.cert, sc.key));
 
     // Convert component proxies to configured proxy lambdas
@@ -403,10 +374,10 @@ const value evalComponent(ServerConf& sc
 /**
  * Return a list of component-name + configured-implementation pairs.
  */
-const list<value> componentToImplementationAssoc(ServerConf& sc, server_rec& server, const list<value>& c) {
+const list<value> componentToImplementationAssoc(ServerConf& sc, const list<value>& c) {
     if (isNil(c))
         return c;
-    return cons<value>(mklist<value>(scdl::name(car(c)), evalComponent(sc, server, car(c))), componentToImplementationAssoc(sc, server, cdr(c)));
+    return cons<value>(mklist<value>(scdl::name(car(c)), evalComponent(sc, car(c))), componentToImplementationAssoc(sc, cdr(c)));
 }
 
 /**
@@ -447,8 +418,8 @@ const failable<list<value> > applyLifecy
 /**
  * Configure the components declared in the deployed composite.
  */
-const failable<bool> confComponents(ServerConf& sc, server_rec& server) {
-    if (sc.contributionPath == "" || sc.compositeName == "")
+const failable<bool> confComponents(ServerConf& sc) {
+    if (!hasCompositeConf(sc))
         return false;
 
     // Chdir to the deployed contribution
@@ -459,7 +430,7 @@ const failable<bool> confComponents(Serv
     const failable<list<value> > comps = readComponents(sc.contributionPath + sc.compositeName);
     if (!hasContent(comps))
         return mkfailure<bool>(reason(comps));
-    sc.implementations = componentToImplementationAssoc(sc, server, content(comps));
+    sc.implementations = componentToImplementationAssoc(sc, content(comps));
     debug(sc.implementations, "modeval::confComponents::implementations");
 
     // Store the implementation lambda functions in a tree for fast retrieval
@@ -486,6 +457,107 @@ const failable<bool> startComponents(Ser
 }
 
 /**
+ * Virtual host scoped server configuration.
+ */
+class VirtualHostConf {
+public:
+    VirtualHostConf(const ServerConf& ssc) : sc(ssc.server) {
+        sc.contributionPath = ssc.virtualHostContributionPath;
+        sc.compositeName = ssc.virtualHostCompositeName;
+        sc.wiringServerName = ssc.wiringServerName;
+        sc.ca = ssc.ca;
+        sc.cert = ssc.cert;
+        sc.key = ssc.key;
+    }
+
+    ~VirtualHostConf() {
+        extern const failable<bool> virtualHostCleanup(const ServerConf& sc);
+        virtualHostCleanup(sc);
+    }
+
+    ServerConf sc;
+};
+
+/**
+ * Configure and start the components deployed in a virtual host.
+ */
+const failable<bool> virtualHostConfig(ServerConf& sc, request_rec* r) {
+    extern const value applyLifecycle(const list<value>&);
+
+    // Determine the server name and wiring server name
+    debug(httpd::serverName(sc.server), "modeval::virtualHostConfig::serverName");
+    debug(httpd::serverName(r), "modeval::virtualHostConfig::virtualHostName");
+    sc.wiringServerName = httpd::serverName(r);
+    debug(sc.wiringServerName, "modeval::virtualHostConfig::wiringServerName");
+
+    // Configure the deployed components
+    debug(sc.contributionPath, "modeval::virtualHostConfig::contributionPath");
+    debug(sc.compositeName, "modeval::virtualHostConfig::compositeName");
+    const failable<bool> cr = confComponents(sc);
+    if (!hasContent(cr))
+        return cr;
+
+    // Start the configured components
+    return startComponents(sc);
+}
+
+/**
+ * Cleanup a virtual host.
+ */
+const failable<bool> virtualHostCleanup(const ServerConf& sc) {
+    if (!hasCompositeConf(sc))
+        return true;
+    debug("modeval::virtualHostCleanup");
+
+    // Stop the component implementations
+    applyLifecycleExpr(sc.implementations, mklist<value>("stop"));
+    return true;
+}
+
+/**
+ * HTTP request handler.
+ */
+int handler(request_rec *r) {
+    if(strcmp(r->handler, "mod_tuscany_eval"))
+        return DECLINED;
+    gc_scoped_pool pool(r->pool);
+    ScopedRequest sr(r);
+    httpdDebugRequest(r, "modeval::handler::input");
+
+    // Get the server configuration
+    const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval);
+
+    // Process dynamic virtual host configuration, if any
+    VirtualHostConf vhc(sc);
+    const bool hasv = hasCompositeConf(vhc.sc);
+    if (hasv) {
+        const failable<bool> cr = virtualHostConfig(vhc.sc, r);
+        if (!hasContent(cr))
+            return httpd::reportStatus(mkfailure<int>(reason(cr)));
+    }
+
+    // Get the component implementation lambda
+    const list<value> path(pathValues(r->uri));
+    const list<value> impl(assoctree<value>(cadr(path), hasv? vhc.sc.implTree : sc.implTree));
+    if (isNil(impl))
+        return httpd::reportStatus(mkfailure<int>(string("Couldn't find component implementation")));
+
+    // Handle HTTP method
+    const lambda<value(const list<value>&)> l(cadr<value>(impl));
+    if (r->header_only)
+         return OK;
+    if(r->method_number == M_GET)
+        return httpd::reportStatus(get(r, l));
+    if(r->method_number == M_POST)
+        return httpd::reportStatus(post(r, l));
+    if(r->method_number == M_PUT)
+        return httpd::reportStatus(put(r, l));
+    if(r->method_number == M_DELETE)
+        return httpd::reportStatus(del(r, l));
+    return HTTP_NOT_IMPLEMENTED;
+}
+
+/**
  * Cleanup callback, called when the server is stopped or restarted.
  */
 apr_status_t serverCleanup(void* v) {
@@ -512,10 +584,14 @@ apr_status_t serverCleanup(void* v) {
 const int postConfigMerge(const ServerConf& mainsc, server_rec* s) {
     if (s == NULL)
         return OK;
+    ostringstream sname;
+    debug(httpd::serverName(s), "modeval::postConfigMerge::serverName");
     ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval);
     sc.wiringServerName = mainsc.wiringServerName;
     sc.contributionPath = mainsc.contributionPath;
     sc.compositeName = mainsc.compositeName;
+    sc.virtualHostContributionPath = mainsc.virtualHostContributionPath;
+    sc.virtualHostCompositeName = mainsc.virtualHostCompositeName;
     sc.ca = mainsc.ca;
     sc.cert = mainsc.cert;
     sc.key = mainsc.key;
@@ -528,7 +604,13 @@ int postConfig(apr_pool_t *p, unused apr
     extern const value applyLifecycle(const list<value>&);
 
     gc_scoped_pool pool(p);
+
+    // Get the server configuration and determine the wiring server name
     ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval);
+    debug(httpd::serverName(s), "modeval::postConfig::serverName");
+    if (sc.wiringServerName == "")
+        sc.wiringServerName = httpd::serverName(s);
+    debug(sc.wiringServerName, "modeval::postConfig::wiringServerName");
 
     // Count the calls to post config
     const string k("tuscany::modeval::postConfig");
@@ -539,6 +621,7 @@ int postConfig(apr_pool_t *p, unused apr
     // count == 1 is the first start, count > 1 is a restart
     if (count == 0)
         return OK;
+
     if (count == 1) {
         debug("modeval::postConfig::start");
         const failable<value> r = failableResult(applyLifecycle(mklist<value>("start")));
@@ -555,10 +638,9 @@ int postConfig(apr_pool_t *p, unused apr
     }
 
     // Configure the deployed components
-    debug(sc.wiringServerName, "modeval::postConfig::wiringServerName");
     debug(sc.contributionPath, "modeval::postConfig::contributionPath");
     debug(sc.compositeName, "modeval::postConfig::compositeName");
-    const failable<bool> res = confComponents(sc, *s);
+    const failable<bool> res = confComponents(sc);
     if (!hasContent(res)) {
         cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl;
         return -1;
@@ -614,6 +696,18 @@ const char* confComposite(cmd_parms *cmd
     sc.compositeName = arg;
     return NULL;
 }
+const char* confVirtualContribution(cmd_parms *cmd, unused void *c, const char *arg) {
+    gc_scoped_pool pool(cmd->pool);
+    ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+    sc.virtualHostContributionPath = arg;
+    return NULL;
+}
+const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) {
+    gc_scoped_pool pool(cmd->pool);
+    ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+    sc.virtualHostCompositeName = arg;
+    return NULL;
+}
 const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
     gc_scoped_pool pool(cmd->pool);
     ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
@@ -646,6 +740,8 @@ const command_rec commands[] = {
     AP_INIT_TAKE1("SCAWiringServerName", (const char*(*)())confWiringServerName, NULL, RSRC_CONF, "SCA wiring server name"),
     AP_INIT_TAKE1("SCAContribution", (const char*(*)())confContribution, NULL, RSRC_CONF, "SCA contribution location"),
     AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, RSRC_CONF, "SCA composite location"),
+    AP_INIT_TAKE1("SCAVirtualContribution", (const char*(*)())confVirtualContribution, NULL, RSRC_CONF, "SCA virtual host contribution location"),
+    AP_INIT_TAKE1("SCAVirtualComposite", (const char*(*)())confVirtualComposite, NULL, RSRC_CONF, "SCA virtual composite location"),
     AP_INIT_TAKE12("SCASetEnv", (const char*(*)())confEnv, NULL, OR_FILEINFO, "Environment variable name and optional value"),
     AP_INIT_TAKE1("SCASSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "SSL CA certificate file"),
     AP_INIT_TAKE1("SCASSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "SSL certificate file"),

Modified: tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp (original)
+++ tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp Tue Jul  6 09:06:07 2010
@@ -44,23 +44,32 @@ namespace server {
 namespace modwiring {
 
 /**
+ * Set to true to wire using mod_proxy, false to wire using HTTP client redirects.
+ */
+const bool useModProxy = true;
+
+/**
  * Server configuration.
  */
 class ServerConf {
 public:
-    ServerConf(server_rec* s) : s(s), contributionPath(""), compositeName("") {
+    ServerConf(server_rec* s) : server(s), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName("") {
     }
-    const server_rec* s;
+    server_rec* server;
     string contributionPath;
     string compositeName;
+    string virtualHostContributionPath;
+    string virtualHostCompositeName;
     list<value> references;
     list<value> services;
 };
 
 /**
- * Set to true to wire using mod_proxy, false to wire using HTTP client redirects.
+ * Return true if a server contains a composite configuration.
  */
-const bool useModProxy = true;
+const bool hasCompositeConf(const ServerConf& sc) {
+    return sc.contributionPath != "" && sc.compositeName != "";
+}
 
 /**
  * Returns true if a URI is absolute.
@@ -73,12 +82,11 @@ const bool isAbsolute(const string& uri)
  * Route a /references/component-name/reference-name request,
  * to the target of the component reference.
  */
-int translateReference(request_rec *r) {
+int translateReference(const ServerConf& sc, request_rec *r) {
     httpdDebugRequest(r, "modwiring::translateReference::input");
     debug(r->uri, "modwiring::translateReference::uri");
 
     // Find the requested component
-    const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring);
     const list<value> rpath(pathValues(r->uri));
     const list<value> comp(assoctree(cadr(rpath), sc.references));
     if (isNil(comp))
@@ -138,12 +146,11 @@ const list<value> assocPath(const value&
 /**
  * Route a service request to the component providing the requested service.
  */
-int translateService(request_rec *r) {
+int translateService(const ServerConf& sc, request_rec *r) {
     httpdDebugRequest(r, "modwiring::translateService::input");
     debug(r->uri, "modwiring::translateService::uri");
 
     // Find the requested component
-    const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring);
     debug(sc.services, "modwiring::translateService::services");
     const list<value> p(pathValues(r->uri));
     const list<value> svc(assocPath(p, sc.services));
@@ -166,44 +173,6 @@ int translateService(request_rec *r) {
 }
 
 /**
- * Translate an HTTP service or reference request and route it
- * to the target component.
- */
-int translate(request_rec *r) {
-    gc_scoped_pool pool(r->pool);
-    if (!strncmp(r->uri, "/components/", 12) != 0)
-        return DECLINED;
-
-    // Translate a component reference request
-    if (!strncmp(r->uri, "/references/", 12) != 0)
-        return translateReference(r);
-
-    // Translate a service request
-    return translateService(r);
-}
-
-/**
- * HTTP request handler, redirect to a target component.
- */
-int handler(request_rec *r) {
-    gc_scoped_pool pool(r->pool);
-    if(strcmp(r->handler, "mod_tuscany_wiring"))
-        return DECLINED;
-    httpdDebugRequest(r, "modwiring::handler::input");
-
-    // Do an internal redirect
-    if (r->filename == NULL || strncmp(r->filename, "/redirect:", 10) != 0)
-        return DECLINED;
-    debug(r->uri, "modwiring::handler::uri");
-    debug(r->filename, "modwiring::handler::filename");
-    debug(r->path_info, "modwiring::handler::path info");
-
-    if (r->args == NULL)
-        return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info)), r);
-    return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info), string(r->args)), r);
-}
-
-/**
  * Read the components declared in a composite.
  */
 const failable<list<value> > readComponents(const string& path) {
@@ -264,7 +233,7 @@ const list<value> uriToComponentAssoc(co
  * Configure the components declared in the server's deployment composite.
  */
 const bool confComponents(ServerConf& sc) {
-    if (sc.contributionPath == "" || sc.compositeName == "")
+    if (!hasCompositeConf(sc))
         return true;
 
     // Read the component configuration and store the references and service URIs
@@ -283,21 +252,109 @@ const bool confComponents(ServerConf& sc
 }
 
 /**
+ * Virtual host scoped server configuration.
+ */
+class VirtualHostConf {
+public:
+    VirtualHostConf(const ServerConf& ssc) : sc(ssc.server) {
+        sc.contributionPath = ssc.virtualHostContributionPath;
+        sc.compositeName = ssc.virtualHostCompositeName;
+    }
+
+    ~VirtualHostConf() {
+    }
+
+    ServerConf sc;
+};
+
+/**
+ * Configure and start the components deployed in a virtual host.
+ */
+const failable<bool> virtualHostConfig(ServerConf& sc, request_rec* r) {
+    debug(httpd::serverName(sc.server), "modwiring::virtualHostConfig::serverName");
+    debug(httpd::serverName(r), "modwiring::virtualHostConfig::virtualHostName");
+
+    // Configure the wiring for the deployed components
+    debug(sc.contributionPath, "modwiring::virtualHostConfig::contributionPath");
+    debug(sc.compositeName, "modwiring::virtualHostConfig::compositeName");
+    confComponents(sc);
+    return true;
+}
+
+/**
+ * Translate an HTTP service or reference request and route it
+ * to the target component.
+ */
+int translate(request_rec *r) {
+    gc_scoped_pool pool(r->pool);
+
+    // No translation needed for a component request
+    if (!strncmp(r->uri, "/components/", 12))
+        return DECLINED;
+
+    // Get the server configuration
+    const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring);
+
+    // Process dynamic virtual host configuration, if any
+    VirtualHostConf vhc(sc);
+    const bool hasv = hasCompositeConf(vhc.sc);
+    if (hasv) {
+        const failable<bool> cr = virtualHostConfig(vhc.sc, r);
+        if (!hasContent(cr))
+            return -1;
+    }
+
+    // Translate a component reference request
+    if (!strncmp(r->uri, "/references/", 12))
+        return translateReference(hasv? vhc.sc: sc, r);
+
+    // Translate a service request
+    return translateService(hasv? vhc.sc : sc, r);
+}
+
+/**
+ * HTTP request handler, redirect to a target component.
+ */
+int handler(request_rec *r) {
+    gc_scoped_pool pool(r->pool);
+    if(strcmp(r->handler, "mod_tuscany_wiring"))
+        return DECLINED;
+    httpdDebugRequest(r, "modwiring::handler::input");
+
+    // Do an internal redirect
+    if (r->filename == NULL || strncmp(r->filename, "/redirect:", 10) != 0)
+        return DECLINED;
+    debug(r->uri, "modwiring::handler::uri");
+    debug(r->filename, "modwiring::handler::filename");
+    debug(r->path_info, "modwiring::handler::path info");
+
+    if (r->args == NULL)
+        return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info)), r);
+    return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info), string(r->args)), r);
+}
+
+/**
  * Called after all the configuration commands have been run.
  * Process the server configuration and configure the wiring for the deployed components.
  */
 const int postConfigMerge(const ServerConf& mainsc, server_rec* s) {
     if (s == NULL)
         return OK;
+    ostringstream sname;
+    debug(httpd::serverName(s), "modwiring::postConfigMerge::serverName");
     ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_wiring);
     sc.contributionPath = mainsc.contributionPath;
     sc.compositeName = mainsc.compositeName;
+    sc.virtualHostContributionPath = mainsc.virtualHostContributionPath;
+    sc.virtualHostCompositeName = mainsc.virtualHostCompositeName;
     sc.references = mainsc.references;
     sc.services = mainsc.services;
     return postConfigMerge(mainsc, s->next);
 }
 
 int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, server_rec *s) {
+    gc_scoped_pool pool(p);
+
     // Count the calls to post config, skip the first one as
     // postConfig is always called twice
     const string k("tuscany::modwiring::postConfig");
@@ -308,6 +365,7 @@ int postConfig(unused apr_pool_t *p, unu
 
     // Configure the wiring for the deployed components
     ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_wiring);
+    debug(httpd::serverName(s), "modwiring::postConfig::serverName");
     debug(sc.contributionPath, "modwiring::postConfig::contributionPath");
     debug(sc.compositeName, "modwiring::postConfig::compositeName");
     confComponents(sc);
@@ -319,9 +377,9 @@ int postConfig(unused apr_pool_t *p, unu
 /**
  * Child process initialization.
  */
-void childInit(apr_pool_t* p, server_rec* svr_rec) {
+void childInit(apr_pool_t* p, server_rec* s) {
     gc_scoped_pool pool(p);
-    ServerConf *conf = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_wiring);
+    ServerConf *conf = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_wiring);
     if(conf == NULL) {
         cerr << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << endl;
         exit(APEXIT_CHILDFATAL);
@@ -343,6 +401,18 @@ const char *confComposite(cmd_parms *cmd
     sc.compositeName = arg;
     return NULL;
 }
+const char *confVirtualContribution(cmd_parms *cmd, unused void *c, const char *arg) {
+    gc_scoped_pool pool(cmd->pool);
+    ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring);
+    sc.virtualHostContributionPath = arg;
+    return NULL;
+}
+const char *confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) {
+    gc_scoped_pool pool(cmd->pool);
+    ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring);
+    sc.virtualHostCompositeName = arg;
+    return NULL;
+}
 
 /**
  * HTTP server module declaration.
@@ -350,6 +420,8 @@ const char *confComposite(cmd_parms *cmd
 const command_rec commands[] = {
     AP_INIT_TAKE1("SCAContribution", (const char*(*)())confContribution, NULL, RSRC_CONF, "SCA contribution location"),
     AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, RSRC_CONF, "SCA composite location"),
+    AP_INIT_TAKE1("SCAVirtualContribution", (const char*(*)())confVirtualContribution, NULL, RSRC_CONF, "SCA virtual host contribution location"),
+    AP_INIT_TAKE1("SCAVirtualComposite", (const char*(*)())confVirtualComposite, NULL, RSRC_CONF, "SCA virtual host composite location"),
     {NULL, NULL, NULL, 0, NO_ARGS, NULL}
 };
 

Modified: tuscany/sca-cpp/trunk/modules/server/server-conf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/server/server-conf?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/server/server-conf (original)
+++ tuscany/sca-cpp/trunk/modules/server/server-conf Tue Jul  6 09:06:07 2010
@@ -39,8 +39,9 @@ fi
 cat >>$root/conf/httpd.conf <<EOF
 # Support for SCA component wiring
 LoadModule mod_tuscany_wiring $here/libmod_tuscany_wiring.so
-SCAWiringServerName $host:$port
+#SCAWiringServerName $host:$port
 
+# Serve HTTP binding JavaScript client code
 Alias /js/tuscany-ref.js $here/htdocs/js/tuscany-ref.js
 
 EOF

Modified: tuscany/sca-cpp/trunk/samples/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/Makefile.am?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/Makefile.am Tue Jul  6 09:06:07 2010
@@ -15,7 +15,7 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql
+SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql store-vhost
 
 sample_DATA = README
 sampledir=$(prefix)/samples

Modified: tuscany/sca-cpp/trunk/samples/store-python/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-python/Makefile.am?rev=960847&r1=960846&r2=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-python/Makefile.am Tue Jul  6 09:06:07 2010
@@ -17,7 +17,7 @@
 
 if WANT_PYTHON
 
-dist_sample_SCRIPTS = start stop ssl-start
+dist_sample_SCRIPTS = start stop ssl-start uec2-start
 sampledir = $(prefix)/samples/store-python
 
 nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/Makefile.am (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/Makefile.am?p2=tuscany/sca-cpp/trunk/samples/store-vhost/Makefile.am&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/Makefile.am Tue Jul  6 09:06:07 2010
@@ -17,12 +17,12 @@
 
 if WANT_PYTHON
 
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
+dist_sample_SCRIPTS = start stop ssl-start uec2-start
+sampledir = $(prefix)/samples/store-vhost
 
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html htdocs/domains/joe/*.html htdocs/domains/jane/*.html
 
 dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+#TESTS = server-test
 
 endif

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/currency-converter.py (from r960846, tuscany/sca-cpp/trunk/samples/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/currency-converter.py?p2=tuscany/sca-cpp/trunk/samples/store-vhost/currency-converter.py&p1=tuscany/sca-cpp/trunk/samples/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/currency-converter.py Tue Jul  6 09:06:07 2010
@@ -15,8 +15,15 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql
+# Currency converter implementation
 
-sample_DATA = README
-sampledir=$(prefix)/samples
+def convert(fr, to, amount):
+    if to == "EUR":
+        return amount * 0.70
+    return amount
+
+def symbol(currency):
+    if currency == "EUR":
+        return "E"
+    return "$"
 

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/fruits-catalog.py (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/fruits-catalog.py?p2=tuscany/sca-cpp/trunk/samples/store-vhost/fruits-catalog.py&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/fruits-catalog.py Tue Jul  6 09:06:07 2010
@@ -15,14 +15,16 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
+# Catalog implementation
 
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
+def getcatalog(converter, currencyCode):
+  code = currencyCode()
+  def convert(price):
+      return converter("convert", "USD", code, price)
+  symbol = converter("symbol", code)
+  return (
+    (("'javaClass", "services.Item"), ("'name", "Apple"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(2.99))),
+    (("'javaClass", "services.Item"), ("'name", "Orange"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(3.55))),
+    (("'javaClass", "services.Item"), ("'name", "Pear"), ("'currencyCode", code), ("'currencySymbol", symbol), ("'price", convert(1.55)))
+  )
 
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
-
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
-
-endif

Added: tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html?rev=960847&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html (added)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html Tue Jul  6 09:06:07 2010
@@ -0,0 +1,157 @@
+<!--
+    * 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="/js/tuscany-ref.js"></script>
+
+<script type="text/javascript">
+var component = new tuscany.sca.Component("Store");
+
+//@Reference
+var catalog = new tuscany.sca.Reference("catalog");
+
+//@Reference
+var shoppingCart = new tuscany.sca.Reference("shoppingCart");
+
+//@Reference
+var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
+
+var catalogItems;
+
+function catalog_getcatalogResponse(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_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.apply("gettotal", shoppingTotal_gettotalResponse);
+    }
+}
+
+function shoppingTotal_gettotalResponse(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>' +
+            '<javaClass>' + catalogItems[i].javaClass + '</javaClass>' +
+            '<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.apply("getcatalog", catalog_getcatalogResponse);
+        shoppingCart.get("", shoppingCart_getResponse);
+    } catch(e){
+        alert(e);
+    }
+}
+</script>
+
+</head>
+
+<body onload="init()">
+<h1>Jane's Store</h1>
+<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>

Added: tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html?rev=960847&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html (added)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html Tue Jul  6 09:06:07 2010
@@ -0,0 +1,157 @@
+<!--
+    * 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="/js/tuscany-ref.js"></script>
+
+<script type="text/javascript">
+var component = new tuscany.sca.Component("Store");
+
+//@Reference
+var catalog = new tuscany.sca.Reference("catalog");
+
+//@Reference
+var shoppingCart = new tuscany.sca.Reference("shoppingCart");
+
+//@Reference
+var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
+
+var catalogItems;
+
+function catalog_getcatalogResponse(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_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.apply("gettotal", shoppingTotal_gettotalResponse);
+    }
+}
+
+function shoppingTotal_gettotalResponse(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>' +
+            '<javaClass>' + catalogItems[i].javaClass + '</javaClass>' +
+            '<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.apply("getcatalog", catalog_getcatalogResponse);
+        shoppingCart.get("", shoppingCart_getResponse);
+    } catch(e){
+        alert(e);
+    }
+}
+</script>
+
+</head>
+
+<body onload="init()">
+<h1>Joe's Store</h1>
+<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>

Added: tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/index.html?rev=960847&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/index.html (added)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/htdocs/index.html Tue Jul  6 09:06:07 2010
@@ -0,0 +1,157 @@
+<!--
+    * 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="/js/tuscany-ref.js"></script>
+
+<script type="text/javascript">
+var component = new tuscany.sca.Component("Store");
+
+//@Reference
+var catalog = new tuscany.sca.Reference("catalog");
+
+//@Reference
+var shoppingCart = new tuscany.sca.Reference("shoppingCart");
+
+//@Reference
+var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
+
+var catalogItems;
+
+function catalog_getcatalogResponse(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_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.apply("gettotal", shoppingTotal_gettotalResponse);
+    }
+}
+
+function shoppingTotal_gettotalResponse(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>' +
+            '<javaClass>' + catalogItems[i].javaClass + '</javaClass>' +
+            '<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.apply("getcatalog", catalog_getcatalogResponse);
+        shoppingCart.get("", shoppingCart_getResponse);
+    } catch(e){
+        alert(e);
+    }
+}
+</script>
+
+</head>
+
+<body onload="init()">
+<h1>Store</h1>
+<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>

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/server-test (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/server-test?p2=tuscany/sca-cpp/trunk/samples/store-vhost/server-test&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/server-test Tue Jul  6 09:06:07 2010
@@ -1,3 +1,5 @@
+#!/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
@@ -15,14 +17,27 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
+echo "Testing..."
+here=`readlink -f $0`; here=`dirname $here`
+curl_prefix=`cat $here/../../modules/http/curl.prefix`
+
+# Setup
+./start
+sleep 2
 
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
+# For this test to work, add the following line to your etc/hosts
+127.0.0.1 jane.store.com joe.store.com
 
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+# Test HTTP GET
+$curl_prefix/bin/curl http://jane.store.com:8090/ 2>/dev/null >tmp/jane.html
+diff tmp/jane.html htdocs/domains/jane/index.html
+rc=$?
 
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+# Cleanup
+./stop
+sleep 2
 
-endif
+if [ "$rc" = "0" ]; then
+    echo "OK"
+fi
+return $rc

Propchange: tuscany/sca-cpp/trunk/samples/store-vhost/server-test
------------------------------------------------------------------------------
    svn:executable = *

Added: tuscany/sca-cpp/trunk/samples/store-vhost/shopping-cart.py
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/shopping-cart.py?rev=960847&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-vhost/shopping-cart.py (added)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/shopping-cart.py Tue Jul  6 09:06:07 2010
@@ -0,0 +1,75 @@
+#  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):
+    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):
+    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):
+    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 gettotal(cache):
+    cart = getcart(cartId, cache)
+    return sum(cart)
+

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start?p2=tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start Tue Jul  6 09:06:07 2010
@@ -1,3 +1,5 @@
+#!/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
@@ -15,14 +17,18 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
-
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
-
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+../../modules/http/httpd-ca-conf tmp localhost
+../../modules/http/httpd-cert-conf tmp localhost
+../../modules/http/httpd-conf tmp localhost 8090 htdocs
+../../modules/http/httpd-ssl-conf tmp localhost 8453 htdocs
+../../modules/server/server-conf tmp
+../../modules/python/python-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+# Configure SCA Composite
+SCAContribution `pwd`/
+SCAComposite store.composite
 
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+EOF
 
-endif
+../../components/cache/memcached-start
+../../modules/http/httpd-start tmp

Propchange: tuscany/sca-cpp/trunk/samples/store-vhost/ssl-start
------------------------------------------------------------------------------
    svn:executable = *

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/start (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/start?p2=tuscany/sca-cpp/trunk/samples/store-vhost/start&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/start Tue Jul  6 09:06:07 2010
@@ -1,3 +1,5 @@
+#!/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
@@ -15,14 +17,15 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
-
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
-
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+../../modules/http/httpd-conf tmp localhost 8090 htdocs vhost
+../../modules/server/server-conf tmp
+../../modules/python/python-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+# Configure SCA Composite for mass dynamic virtual Hosting
+SCAVirtualContribution `pwd`/
+SCAVirtualComposite store.composite
 
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+EOF
 
-endif
+../../components/cache/memcached-start
+../../modules/http/httpd-start tmp

Propchange: tuscany/sca-cpp/trunk/samples/store-vhost/start
------------------------------------------------------------------------------
    svn:executable = *

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/stop (from r960846, tuscany/sca-cpp/trunk/samples/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/stop?p2=tuscany/sca-cpp/trunk/samples/store-vhost/stop&p1=tuscany/sca-cpp/trunk/samples/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/stop Tue Jul  6 09:06:07 2010
@@ -1,3 +1,5 @@
+#!/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
@@ -15,8 +17,5 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql
-
-sample_DATA = README
-sampledir=$(prefix)/samples
-
+../../modules/http/httpd-stop tmp
+../../components/cache/memcached-stop

Propchange: tuscany/sca-cpp/trunk/samples/store-vhost/stop
------------------------------------------------------------------------------
    svn:executable = *

Added: tuscany/sca-cpp/trunk/samples/store-vhost/store.composite
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/store.composite?rev=960847&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-vhost/store.composite (added)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/store.composite Tue Jul  6 09:06:07 2010
@@ -0,0 +1,69 @@
+<?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="ShoppingCart">
+            <t:binding.atom uri="shoppingCart"/>
+        </service>        
+        <service name="Total">
+            <t:binding.jsonrpc uri="total"/>
+        </service>        
+        <reference name="cache" target="Cache"/>
+    </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.cpp path="../../components/cache" library="libmemcache"/>
+        <service name="Cache">
+            <t:binding.atom uri="cache"/>
+        </service>
+    </component>     
+
+</composite>

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/store.py (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/store.py?p2=tuscany/sca-cpp/trunk/samples/store-vhost/store.py&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/store.py Tue Jul  6 09:06:07 2010
@@ -15,14 +15,26 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
+# Store implementation
 
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
+def post(item, catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("post", item)
 
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+def getall(catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("getall")
 
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+def get(id, catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("get", id)
+
+def getcatalog(catalog, shoppingCart, shoppingTotal):
+    return catalog("getcatalog")
+
+def gettotal(catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("gettotal")
+
+def deleteall(catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("deleteall")
+
+def delete(id, catalog, shoppingCart, shoppingTotal):
+    return shoppingCart("delete", id)
 
-endif

Copied: tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start (from r960846, tuscany/sca-cpp/trunk/samples/store-python/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start?p2=tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start&p1=tuscany/sca-cpp/trunk/samples/store-python/Makefile.am&r1=960846&r2=960847&rev=960847&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/samples/store-python/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start Tue Jul  6 09:06:07 2010
@@ -1,3 +1,5 @@
+#!/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
@@ -15,14 +17,30 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-if WANT_PYTHON
+# Pass your EC2 public host name
+if [ "$1" != "" ]; then
+    host=$1
+else
+    host="localhost"
+fi
+
+# Ports 80, 443, 8090, 8453 need to be open
+sudo ../../ubuntu/ip-redirect 80 8090
+sudo ../../ubuntu/ip-redirect 443 8453
 
-dist_sample_SCRIPTS = start stop ssl-start
-sampledir = $(prefix)/samples/store-python
+../../modules/http/httpd-ca-conf tmp $host
+../../modules/http/httpd-cert-conf tmp $host
+../../modules/http/httpd-conf tmp $host 8090/80 htdocs
+../../modules/http/httpd-ssl-conf tmp $host 8453/443 htdocs
+../../modules/server/server-conf tmp
+../../modules/python/python-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+# Configure SCA Composite
+SCAContribution `pwd`/
+SCAComposite store.composite
 
-nobase_dist_sample_DATA = currency-converter.py fruits-catalog.py shopping-cart.py store.py store.composite htdocs/*.html
+EOF
 
-dist_noinst_SCRIPTS = server-test
-TESTS = server-test
+../../components/cache/memcached-start
+../../modules/http/httpd-start tmp
 
-endif

Propchange: tuscany/sca-cpp/trunk/samples/store-vhost/uec2-start
------------------------------------------------------------------------------
    svn:executable = *