Add support for HTTPD mass dynamic virtual hosting. Components can now be deployed, resolved, wired and invoked within a virtual host.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@960847 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0389017140
commit
4b05b5d35a
23 changed files with 1249 additions and 123 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_prefix}/modules/mod_setenvif.so
|
|||
<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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -74,6 +74,31 @@ template<typename C> C& serverConf(const cmd_parms *cmd, const module* mod) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -295,7 +320,7 @@ const bool redirectFilters(ap_filter_t* f, request_rec* from, request_rec* to) {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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* nr) {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -68,6 +70,13 @@ public:
|
|||
list<value> implTree;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
@ -240,57 +249,6 @@ int translate(request_rec *r) {
|
|||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store current HTTP request for access from property lambda functions.
|
||||
*/
|
||||
#ifdef WANT_THREADS
|
||||
__thread
|
||||
#endif
|
||||
const request_rec* currentRequest = NULL;
|
||||
|
||||
class scoped_request {
|
||||
public:
|
||||
scoped_request(const request_rec* r) {
|
||||
currentRequest = r;
|
||||
}
|
||||
|
||||
~scoped_request() {
|
||||
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.
|
||||
*/
|
||||
|
|
@ -304,6 +262,25 @@ const list<value> refProxies(const list<value>& refs, const string& base, const
|
|||
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
|
||||
__thread
|
||||
#endif
|
||||
const request_rec* currentRequest = NULL;
|
||||
|
||||
class ScopedRequest {
|
||||
public:
|
||||
ScopedRequest(const request_rec* r) {
|
||||
currentRequest = r;
|
||||
}
|
||||
|
||||
~ScopedRequest() {
|
||||
currentRequest = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -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, server_rec& server, const value& comp)
|
|||
/**
|
||||
* 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> > applyLifecycleExpr(const list<value>& impls, const
|
|||
/**
|
||||
* 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(ServerConf& sc, server_rec& server) {
|
|||
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
|
||||
|
|
@ -485,6 +456,107 @@ const failable<bool> startComponents(ServerConf& sc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -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_pool_t *plog, unused apr_pool_t *ptemp,
|
|||
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_pool_t *plog, unused apr_pool_t *ptemp,
|
|||
// 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_pool_t *plog, unused apr_pool_t *ptemp,
|
|||
}
|
||||
|
||||
// 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, unused void *c, const char *arg) {
|
|||
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"),
|
||||
|
|
|
|||
|
|
@ -43,24 +43,33 @@ namespace tuscany {
|
|||
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& k, const list<value>& tree) {
|
|||
/**
|
||||
* 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));
|
||||
|
|
@ -165,44 +172,6 @@ int translateService(request_rec *r) {
|
|||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -264,7 +233,7 @@ const list<value> uriToComponentAssoc(const list<value>& c) {
|
|||
* 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
|
||||
|
|
@ -282,6 +251,88 @@ const bool confComponents(ServerConf& sc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
@ -289,15 +340,21 @@ const bool confComponents(ServerConf& sc) {
|
|||
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, unused apr_pool_t *plog, unused apr_pool_t
|
|||
|
||||
// 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, unused apr_pool_t *plog, unused apr_pool_t
|
|||
/**
|
||||
* 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, unused void *c, const char *arg) {
|
|||
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, unused void *c, const char *arg) {
|
|||
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}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
28
sca-cpp/trunk/samples/store-vhost/Makefile.am
Normal file
28
sca-cpp/trunk/samples/store-vhost/Makefile.am
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 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
|
||||
|
||||
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 htdocs/domains/joe/*.html htdocs/domains/jane/*.html
|
||||
|
||||
dist_noinst_SCRIPTS = server-test
|
||||
#TESTS = server-test
|
||||
|
||||
endif
|
||||
29
sca-cpp/trunk/samples/store-vhost/currency-converter.py
Normal file
29
sca-cpp/trunk/samples/store-vhost/currency-converter.py
Normal file
|
|
@ -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 "$"
|
||||
|
||||
30
sca-cpp/trunk/samples/store-vhost/fruits-catalog.py
Normal file
30
sca-cpp/trunk/samples/store-vhost/fruits-catalog.py
Normal file
|
|
@ -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 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)))
|
||||
)
|
||||
|
||||
157
sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html
Normal file
157
sca-cpp/trunk/samples/store-vhost/htdocs/domains/jane/index.html
Normal file
|
|
@ -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>
|
||||
157
sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html
Normal file
157
sca-cpp/trunk/samples/store-vhost/htdocs/domains/joe/index.html
Normal file
|
|
@ -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>
|
||||
157
sca-cpp/trunk/samples/store-vhost/htdocs/index.html
Normal file
157
sca-cpp/trunk/samples/store-vhost/htdocs/index.html
Normal file
|
|
@ -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>
|
||||
43
sca-cpp/trunk/samples/store-vhost/server-test
Executable file
43
sca-cpp/trunk/samples/store-vhost/server-test
Executable file
|
|
@ -0,0 +1,43 @@
|
|||
#!/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
|
||||
sleep 2
|
||||
|
||||
# For this test to work, add the following line to your etc/hosts
|
||||
127.0.0.1 jane.store.com joe.store.com
|
||||
|
||||
# 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=$?
|
||||
|
||||
# Cleanup
|
||||
./stop
|
||||
sleep 2
|
||||
|
||||
if [ "$rc" = "0" ]; then
|
||||
echo "OK"
|
||||
fi
|
||||
return $rc
|
||||
75
sca-cpp/trunk/samples/store-vhost/shopping-cart.py
Normal file
75
sca-cpp/trunk/samples/store-vhost/shopping-cart.py
Normal file
|
|
@ -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)
|
||||
|
||||
34
sca-cpp/trunk/samples/store-vhost/ssl-start
Executable file
34
sca-cpp/trunk/samples/store-vhost/ssl-start
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/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/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
|
||||
|
||||
EOF
|
||||
|
||||
../../components/cache/memcached-start
|
||||
../../modules/http/httpd-start tmp
|
||||
31
sca-cpp/trunk/samples/store-vhost/start
Executable file
31
sca-cpp/trunk/samples/store-vhost/start
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/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/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
|
||||
|
||||
EOF
|
||||
|
||||
../../components/cache/memcached-start
|
||||
../../modules/http/httpd-start tmp
|
||||
21
sca-cpp/trunk/samples/store-vhost/stop
Executable file
21
sca-cpp/trunk/samples/store-vhost/stop
Executable file
|
|
@ -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/http/httpd-stop tmp
|
||||
../../components/cache/memcached-stop
|
||||
69
sca-cpp/trunk/samples/store-vhost/store.composite
Normal file
69
sca-cpp/trunk/samples/store-vhost/store.composite
Normal file
|
|
@ -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>
|
||||
40
sca-cpp/trunk/samples/store-vhost/store.py
Normal file
40
sca-cpp/trunk/samples/store-vhost/store.py
Normal file
|
|
@ -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 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)
|
||||
|
||||
46
sca-cpp/trunk/samples/store-vhost/uec2-start
Executable file
46
sca-cpp/trunk/samples/store-vhost/uec2-start
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#!/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.
|
||||
|
||||
# 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
|
||||
|
||||
../../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
|
||||
|
||||
EOF
|
||||
|
||||
../../components/cache/memcached-start
|
||||
../../modules/http/httpd-start tmp
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue