diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2011-11-10 02:36:40 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2011-11-10 02:36:40 +0000 |
commit | 52cd682405f7a052d45d83b66cc75f19316ceffe (patch) | |
tree | 6b76eeddb2d4682db61f8e38462413bc40b59a3d /sca-cpp | |
parent | 629c1f267e5f7a835891e36ebdae8404740f13e2 (diff) |
Enable multiple apps to co-exist under different paths in a single Virtual Host and Internet domain.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1200105 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp')
28 files changed, 378 insertions, 429 deletions
diff --git a/sca-cpp/trunk/components/constdb/tinycdb.hpp b/sca-cpp/trunk/components/constdb/tinycdb.hpp index e26001dc59..514133b0e1 100644 --- a/sca-cpp/trunk/components/constdb/tinycdb.hpp +++ b/sca-cpp/trunk/components/constdb/tinycdb.hpp @@ -90,6 +90,18 @@ const bool free(const buffer&b) { } /** + * Convert a database name to an absolute path. + */ +const string absdbname(const string& name) { + if (length(name) == 0 || c_str(name)[0] == '/') + return name; + char cwd[512]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + return name; + return string(cwd) + "/" + name; +} + +/** * Represents a TinyCDB connection. */ class TinyCDB { @@ -99,7 +111,7 @@ public: st.st_ino = 0; } - TinyCDB(const string& name) : owner(true), name(name), fd(-1) { + TinyCDB(const string& name) : owner(true), name(absdbname(name)), fd(-1) { debug(name, "tinycdb::tinycdb::name"); st.st_ino = 0; } diff --git a/sca-cpp/trunk/components/filedb/filedb.cpp b/sca-cpp/trunk/components/filedb/filedb.cpp index 473dfea281..5f755de3eb 100644 --- a/sca-cpp/trunk/components/filedb/filedb.cpp +++ b/sca-cpp/trunk/components/filedb/filedb.cpp @@ -103,7 +103,8 @@ const failable<value> start(const list<value>& params) { // Connect to the configured database and table const value dbname = ((lambda<value(list<value>)>)car(params))(list<value>()); const value format = ((lambda<value(list<value>)>)cadr(params))(list<value>()); - filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(dbname, format)); + + filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(absdbname(dbname), format)); // Return the component implementation lambda function return value(lambda<value(const list<value>&)>(applyfiledb(db))); diff --git a/sca-cpp/trunk/components/filedb/filedb.hpp b/sca-cpp/trunk/components/filedb/filedb.hpp index d2bc8bd212..993003ce8e 100644 --- a/sca-cpp/trunk/components/filedb/filedb.hpp +++ b/sca-cpp/trunk/components/filedb/filedb.hpp @@ -40,6 +40,18 @@ namespace tuscany { namespace filedb { /** + * Convert a database name to an absolute path. + */ +const string absdbname(const string& name) { + if (length(name) == 0 || c_str(name)[0] == '/') + return name; + char cwd[512]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + return name; + return string(cwd) + "/" + name; +} + +/** * Represents a FileDB connection. */ class FileDB { @@ -48,7 +60,7 @@ public: debug("filedb::filedb"); } - FileDB(const string& name, const string& format) : owner(true), name(name), format(format) { + FileDB(const string& name, const string& format) : owner(true), name(absdbname(name)), format(format) { debug(name, "filedb::filedb::name"); debug(format, "filedb::filedb::format"); } diff --git a/sca-cpp/trunk/components/kvdb/leveldb.hpp b/sca-cpp/trunk/components/kvdb/leveldb.hpp index 893166c361..96e404a6e4 100644 --- a/sca-cpp/trunk/components/kvdb/leveldb.hpp +++ b/sca-cpp/trunk/components/kvdb/leveldb.hpp @@ -90,6 +90,18 @@ const bool free(const buffer&b) { } /** + * Convert a database name to an absolute path. + */ +const string absdbname(const string& name) { + if (length(name) == 0 || c_str(name)[0] == '/') + return name; + char cwd[512]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + return name; + return string(cwd) + "/" + name; +} + +/** * Represents a LevelDB connection. */ class LevelDB { @@ -99,7 +111,7 @@ public: st.st_ino = 0; } - LevelDB(const string& name) : owner(true), name(name), fd(-1) { + LevelDB(const string& name) : owner(true), name(absdbname(name)), fd(-1) { debug(name, "leveldb::leveldb::name"); st.st_ino = 0; } diff --git a/sca-cpp/trunk/modules/edit/edit.composite b/sca-cpp/trunk/modules/edit/edit.composite index 85ae67d8b4..0e348fd105 100644 --- a/sca-cpp/trunk/modules/edit/edit.composite +++ b/sca-cpp/trunk/modules/edit/edit.composite @@ -48,6 +48,13 @@ <reference name="log" target="Log"/> </component> + <component name="AppWidget"> + <implementation.widget location="/app/index.html"/> + <reference name="user" target="User"/> + <reference name="pages" target="Pages"/> + <reference name="log" target="Log"/> + </component> + <component name="Accounts"> <implementation.python script="accounts.py"/> <service name="Accounts"> diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf index 0be3e662d7..b478c7cd3d 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf +++ b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf @@ -3,7 +3,6 @@ CACHE MANIFEST # Version 5 # App resources -/ /favicon.ico /notauth/ /notfound/ diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/index.html b/sca-cpp/trunk/modules/edit/htdocs/app/index.html index 773d2adf90..97ea0a3f79 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/app/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/app/index.html @@ -17,7 +17,7 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> +<html manifest="cache-manifest.cmf"> <head> <title></title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"/> @@ -87,8 +87,13 @@ $('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig-min.js'))); <script type="text/javascript"> -// Set the document title -document.title = location.hostname.split('.')[0]; +/** + * Get the app name + */ +var appname = location.pathname.split('/')[1]; + +// Set page title +document.title = appname; /** * The main page div. @@ -98,12 +103,13 @@ var contentdiv = $('content'); /** * Initialize the app HTTP clients. */ -var pagecomp = sca.httpclient('page', ''); -var startcomp = sca.httpclient('start', '/start'); -var stopcomp = sca.httpclient('stop', '/stop'); -var timercomp = sca.httpclient('timer', '/timer'); -var animationcomp = sca.httpclient('animation', '/animation'); -var locationcomp = sca.httpclient('location', '/location'); +var appWidget = sca.component('AppWidget'); +var pagecomp = sca.reference(appWidget, 'pages'); +var startcomp = sca.httpclient('start', '/' + appname + '/start'); +var stopcomp = sca.httpclient('stop', '/' + appname + '/stop'); +var timercomp = sca.httpclient('timer', '/' + appname + '/timer'); +var animationcomp = sca.httpclient('animation', '/' + appname + '/animation'); +var locationcomp = sca.httpclient('location', '/' + appname + '/location'); /** * Pre-fetch app resources. @@ -414,11 +420,11 @@ function docdata(doc) { /** * Bind a handler to a widget. */ -function bindwidgethandler(e) { +function bindwidgethandler(e, appname) { if (e.className == 'button') { var b = car(childElements(e)); b.name = e.id; - b.onclick = function() { return buttonClickHandler(b.value); }; + b.onclick = function() { return buttonClickHandler(b.value, appname); }; return e; } if (e.className == 'link') { @@ -427,7 +433,7 @@ function bindwidgethandler(e) { if (hr.substring(0, 5) == 'link:' && hr.indexOf('://') == -1) { var f = function(e) { e.preventDefault(); - return buttonClickHandler(hr.substring(5)); + return buttonClickHandler(hr.substring(5), appname); }; l.ontouchstart = l.onclick = f; l.href = 'javascript:void()'; @@ -528,7 +534,7 @@ function initwidget(e) { /** * Get app data from the main app page component. */ -function getpagedata() { +function getpagedata(appname) { try { // Display component data on the page @@ -552,7 +558,7 @@ function getpagedata() { function setupwidget(e) { initwidget(e); fixupwidget(e); - bindwidgethandler(e); + bindwidgethandler(e, appname); } // Setup the widgets @@ -634,10 +640,10 @@ function compquery() { /** * Handle a button click event. */ -function buttonClickHandler(id) { +function buttonClickHandler(id, appname) { try { var uri = compquery(); - return sca.component(id).get(uri, function(doc, e) { + return sca.component(id, appname).get(uri, function(doc, e) { if (isNil(doc)) { log('error on get(button, ' + uri + ')', e); return false; @@ -824,8 +830,21 @@ function setupLocationHandler() { return true; } +/** + * Return the page in an ATOM entry. + */ +function atompage(doc) { + var entry = atom.readATOMEntry(mklist(doc)); + if (isNil(entry)) + return mklist(); + var content = namedElementChild("'content", car(entry)); + if (content == null) + return mklist(); + return elementChildren(content); +} + // Load the app page -pagecomp.get('app.html', function(doc, e) { +pagecomp.get(appname, function(doc, e) { //log('page get'); if (isNil(doc)) { log('error getting app page', e); @@ -833,10 +852,12 @@ pagecomp.get('app.html', function(doc, e) { } // Set the app HTML page into the content div - contentdiv.innerHTML = doc; + //log('page', doc); + var el = atompage(doc); + contentdiv.innerHTML = writeStrings(writeXML(el, false)); // Merge in the app data - getpagedata(); + getpagedata(appname); }); /** diff --git a/sca-cpp/trunk/modules/edit/htdocs/clone/index.html b/sca-cpp/trunk/modules/edit/htdocs/clone/index.html index dd041e591e..3642634ed6 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/clone/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/clone/index.html @@ -35,7 +35,7 @@ <form id="cloneAppForm"> <table style="width: 100%;"> <tr><td><b>New App Name:</b></td></tr> -<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/> <span id="appDomain"></span></td></tr> +<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr> <tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr> @@ -56,23 +56,10 @@ // Get the app name var appname = ui.fragmentParams(location)['app']; -/** - * Return the link to an app. - */ -function applink(appname) { - var protocol = location.protocol; - var host = location.hostname; - var port = ':' + location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/'; - return link; -} - // Set page titles var tclone = isNil(config.clone)? 'Clone' : config.clone; document.title = ui.windowtitle(location.hostname) + ' - ' + tclone + ' - ' + appname; -$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; +$('appNameHeader').innerHTML = '<a href=\"/' + appname + '/\" target=\"' + '_blank' + '\">' + appname + '</a>'; $('th').innerHTML = tclone + ' this App'; $('cloneAppOKButton').value = tclone; $('cloneAppOKButton').title = tclone + ' this app'; @@ -80,9 +67,6 @@ $('cloneAppOKButton').title = tclone + ' this app'; // Set images $('appimg').src = ui.b64img(appcache.get('/public/app.b64')); -// Init form -$('appDomain').innerHTML = '.' + location.hostname; - // Init service references var editWidget = sca.component("EditWidget"); var dashboards = sca.reference(editWidget, "dashboards"); diff --git a/sca-cpp/trunk/modules/edit/htdocs/create/index.html b/sca-cpp/trunk/modules/edit/htdocs/create/index.html index c74c00950d..6097053cd6 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/create/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/create/index.html @@ -35,7 +35,7 @@ <form id="createAppForm"> <table style="width: 100%;"> <tr><td><b>App Name:</b></td></tr> -<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/> <span id="appDomain"></span></td></tr> +<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr> <tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr> @@ -60,9 +60,6 @@ $('h1').innerHTML = ui.hometitle(location.hostname); // Set images $('appimg').src = ui.b64img(appcache.get('/public/app.b64')); -// Init form -$('appDomain').innerHTML = '.' + location.hostname; - // Init service references var editWidget = sca.component("EditWidget"); var dashboards = sca.reference(editWidget, "dashboards"); diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html index 77fa1d4888..1732590079 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html @@ -68,22 +68,9 @@ if (isNil(appname)) { ispalette = true; } -/** - * Return the link to an app. - */ -function applink(appname) { - var protocol = location.protocol; - var host = location.hostname; - var port = ':' + location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/'; - return link; -} - // Set page titles document.title = ui.windowtitle(location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname; -$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; +$('appNameHeader').innerHTML = '<a href=\"/' + appname + '/\" target=\"' + '_blank' + '\">' + appname + '</a>'; /** * Component value field, add, delete and play buttons. @@ -2060,7 +2047,7 @@ function complink(appname, cname) { var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/c/' + cname; + var link = protocol + '//' + host + port + '/' + appname + '/c/' + cname; return link; } @@ -2090,8 +2077,7 @@ function showdata(gcomp) { return true; if (isNil(gcomp)) return true; - var clink = complink(appname, gcomp.id); - cvalue.value = clink; + cvalue.value = complink(appname, gcomp.id); cplay.innerHTML = '<'; gvisible = false; pdiv.innerHTML = ''; diff --git a/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html b/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html index 4665e9f571..b44ccb26e9 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html @@ -113,7 +113,7 @@ function showmenu(mdiv) { mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); } -showmenu($('menu')); +showmenu(mdiv); cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); /** diff --git a/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html b/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html index 8601fbfea6..6b3bb09824 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html @@ -115,7 +115,7 @@ function showmenu(mdiv) { } showmenu(mdiv); -div.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); +cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); /** * Handle orientation change. diff --git a/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html b/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html index 60c774d8ea..d01e535299 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html @@ -114,7 +114,7 @@ function showmenu(mdiv) { mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); } -showmenu($('menu')); +showmenu(mdiv); cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); /** diff --git a/sca-cpp/trunk/modules/edit/htdocs/oops/index.html b/sca-cpp/trunk/modules/edit/htdocs/oops/index.html index 67408d8d62..aeb5ae5d2c 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/oops/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/oops/index.html @@ -113,7 +113,7 @@ function showmenu(mdiv) { mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); } -showmenu($('menu')); +showmenu(mdiv); cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); /** diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/index.html b/sca-cpp/trunk/modules/edit/htdocs/page/index.html index 7df8a1a1d9..9482cb4e32 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/page/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/page/index.html @@ -100,13 +100,13 @@ function applink(appname) { var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/'; + var link = protocol + '//' + host + port + '/' + appname + '/'; return link; } // Set page titles document.title = ui.windowtitle(location.hostname) + ' - Page - ' + appname; -$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; +$('appNameHeader').innerHTML = '<a href=\"/' + appname + '/\" target=\"' + '_blank' + '\">' + appname + '</a>'; /** * Page editor area, widget value field, add, delete and play page buttons. @@ -149,8 +149,8 @@ resizeFields(); window.onresize = resizeFields; // Init component references -var editWidget = sca.component("EditWidget"); -var pages = sca.reference(editWidget, "pages"); +var editWidget = sca.component('EditWidget'); +var pages = sca.reference(editWidget, 'pages'); /** * Page editing functions. @@ -763,7 +763,7 @@ function getpage(name, ediv) { if (isNil(el)) buffer.innerHTML = '<div id="page"></div>'; else - buffer.innerHTML = writeStrings(writeXML(atompage(doc), false)); + buffer.innerHTML = writeStrings(writeXML(el, false)); // Remove any existing page nodes from the editor div var fnodes = filter(function(e) { @@ -941,8 +941,8 @@ function playpage() { evisible = false; pdiv.style.visibility = 'visible'; pdiv.innerHTML = ''; - pdiv.innerHTML = '<iframe id="playappframe" style="position: relative; height: 5000px; width: 2500px; border: 0px;" scrolling="no" frameborder="0" src="' + - applink(appname) + '"></iframe>'; + pdiv.innerHTML = '<iframe id="playappframe" style="position: relative; height: 5000px; width: 2500px; border: 0px;" scrolling="no" frameborder="0" src="/' + + appname + '"></iframe>'; setTimeout(function() { ediv.style.visibility = 'hidden' }, 0); diff --git a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html index f049bea8a5..81f06c95e4 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html @@ -56,22 +56,9 @@ // Get the app name var appname = ui.fragmentParams(location)['app']; -/** - * Return the link to an app. - */ -function applink(appname) { - var protocol = location.protocol; - var host = location.hostname; - var port = ':' + location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/'; - return link; -} - // Set page titles document.title = ui.windowtitle(location.hostname) + ' - Stats - ' + appname; -$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; +$('appNameHeader').innerHTML = '<a href=\"/' + appname + '/\" target=\"' + '_blank' + '\">' + appname + '</a>'; var tclone = isNil(config.clone)? 'Clone' : config.clone; $('cloneApp').value = tclone; $('cloneApp').title = tclone + ' this app'; diff --git a/sca-cpp/trunk/modules/edit/htdocs/store/index.html b/sca-cpp/trunk/modules/edit/htdocs/store/index.html index e82d675f22..bcb3ba7c85 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/store/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/store/index.html @@ -78,19 +78,6 @@ var store = sca.reference(editWidget, "store"); var dashboards = sca.reference(editWidget, "dashboards"); /** - * Return the link to an app. - */ -function applink(appname) { - var protocol = location.protocol; - var host = location.hostname; - var port = ':' + location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/'; - return link; -} - -/** * Edit an app. */ function editApp(appname) { @@ -151,7 +138,7 @@ function getapps(category) { apps += '<div>' + ui.ahref('/#view=stats&app=' + name, '_view', '<img src="' + appimg + '" width="50" height="50" style="height: 50px; width: 50px; vertical-align: top; margin: 0px; padding: 0px;"></img>') + '</div>'; apps += '</td>'; apps += '<td class="tdw">'; - apps += '<div style="font-weight: bold">' + ui.ahref(applink(name), '_blank', name) + '</div>'; + apps += '<div style="font-weight: bold">' + ui.ahref('/' + name + '/', '_blank', name) + '</div>'; if (category == 'myapps') apps += '<div style="color: #808080;">Shared</div>'; else diff --git a/sca-cpp/trunk/modules/edit/ssl-start b/sca-cpp/trunk/modules/edit/ssl-start index 050de3e83c..919a19f4bb 100755 --- a/sca-cpp/trunk/modules/edit/ssl-start +++ b/sca-cpp/trunk/modules/edit/ssl-start @@ -17,8 +17,8 @@ # specific language governing permissions and limitations # under the License. -# For this module to work, add the app domains to your /etc/hosts as follows: -# 127.0.0.1 sca-store.com abc.sca-store.com xyz.sca-store.com ... +# For this module to work, add the sca-store.com domain to your /etc/hosts as follows: +# 127.0.0.1 sca-store.com here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python` @@ -26,14 +26,11 @@ jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python` # Create SSL certificates ../../modules/http/ssl-ca-conf tmp sca-store.com ../../modules/http/ssl-cert-conf tmp sca-store.com server -../../modules/http/ssl-cert-conf tmp *.sca-store.com vhost -# Configure server with virtual hosting +# Configure server ../../modules/http/httpd-conf tmp sca-store.com 8090 htdocs ../../modules/http/httpd-event-conf tmp -../../modules/http/vhost-conf tmp apps htdocs ../../modules/http/httpd-ssl-conf tmp 8453 -../../modules/http/vhost-ssl-conf tmp # Configure authentication ../../modules/http/open-auth-conf tmp @@ -55,15 +52,6 @@ ErrorDocument 404 /notfound/ ErrorDocument 401 /notauth/ ErrorDocument 500 /oops/ -EOF - -# Configure app home pages -cat >>tmp/conf/dvhost-ssl.conf <<EOF -# App error pages -ErrorDocument 404 /notfound/ -ErrorDocument 401 /notauth/ -ErrorDocument 500 /oops/ - # Redirect www to main home page RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.sca-store\.com [NC] @@ -74,17 +62,6 @@ RewriteRule .* https://sca-store.com%{REQUEST_URI} [L,R] EOF -cat >>tmp/conf/dvhost.conf <<EOF -# Redirect www to main home page -RewriteEngine on -RewriteCond %{HTTP_HOST} ^www\.sca-store\.com [NC] -RewriteCond %{SERVER_PORT} !^80$ -RewriteRule .* http://sca-store.com:%{SERVER_PORT}%{REQUEST_URI} [L,R] -RewriteCond %{HTTP_HOST} ^www\.sca-store\.com [NC] -RewriteRule .* http://sca-store.com%{REQUEST_URI} [L,R] - -EOF - # Configure SCA contributions cat >>tmp/conf/httpd.conf <<EOF @@ -98,7 +75,7 @@ SCAVirtualComposite app.composite EOF -# Configure main aliases +# Configure resource aliases cat >>tmp/conf/httpd.conf <<EOF Alias /home/home.png $here/htdocs/home/home.png @@ -109,24 +86,21 @@ EOF # Create app links and sub-directories if needed ./mkapplinks -# Configure app aliases -cat >>tmp/conf/dvhost-ssl.conf <<EOF -# Configure aliases -Alias /cache-manifest.cmf $here/htdocs/app/cache-manifest.cmf -Alias /data $here/htdocs/data -Alias /favicon.ico $here/htdocs/favicon.ico -Alias /footconfig.js $here/htdocs/footconfig.js -Alias /frame.html $here/htdocs/app/frame.html -Alias /headconfig.js $here/htdocs/headconfig.js -Alias /index.html $here/htdocs/app/index.html -Alias /login $here/htdocs/login -Alias /logout $here/htdocs/logout -Alias /notauth $here/htdocs/notauth -Alias /notfound $here/htdocs/notfound -Alias /notyet $here/htdocs/notyet -Alias /oops $here/htdocs/oops -Alias /public $here/htdocs/public -Alias /robots.txt $here/htdocs/robots.txt +# Configure app resource aliases +cat >>tmp/conf/svhost-ssl.conf <<EOF + +<Location /v> +RewriteEngine on + +# Map /v/<app-name>/<path> to htdocs/app/<path> +RewriteCond %{REQUEST_URI} ^/v/.+/.*$ +RewriteRule /v/(.+)/(.*)$ $here/htdocs/app/\$2 [L] + +# Redirect /v/<app-name> to /<app-name>/ +RewriteCond %{REQUEST_URI} ^/v/[^/]+$ +RewriteRule /v/([^/]+)$ /\$1/ [L,R] + +</Location> EOF @@ -137,5 +111,5 @@ mkdir -p tmp/appdata/filedb ../../components/cache/memcached-start # Start server -../../modules/http/httpd-start tmp +../http/httpd-start tmp diff --git a/sca-cpp/trunk/modules/edit/start b/sca-cpp/trunk/modules/edit/start index b9fe5953d6..b2608b245d 100755 --- a/sca-cpp/trunk/modules/edit/start +++ b/sca-cpp/trunk/modules/edit/start @@ -17,16 +17,15 @@ # specific language governing permissions and limitations # under the License. -# For this module to work, add the app domains to your /etc/hosts as follows: -# 127.0.0.1 sca-store.com abc.sca-store.com xyz.sca-store.com ... +# For this module to work, add the sca-store.com domain to your /etc/hosts as follows: +# 127.0.0.1 sca-store.com here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python` -# Configure server with virtual hosting +# Configure server ../../modules/http/httpd-conf tmp sca-store.com 8090 htdocs ../../modules/http/httpd-event-conf tmp -../../modules/http/vhost-conf tmp apps htdocs # Configure Python component support ../server/server-conf tmp @@ -39,15 +38,6 @@ ErrorDocument 404 /notfound/ ErrorDocument 401 /notauth/ ErrorDocument 500 /oops/ -EOF - -# Configure app home pages -cat >>tmp/conf/dvhost.conf <<EOF -# App error pages -ErrorDocument 404 /notfound/ -ErrorDocument 401 /notauth/ -ErrorDocument 500 /oops/ - # Redirect www to main home page RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.sca-store\.com [NC] @@ -70,7 +60,7 @@ SCAVirtualComposite app.composite EOF -# Configure main aliases +# Configure resource aliases cat >>tmp/conf/httpd.conf <<EOF Alias /home/home.png $here/htdocs/home/home.png @@ -81,24 +71,21 @@ EOF # Create app links and sub-directories if needed ./mkapplinks -# Configure app aliases -cat >>tmp/conf/dvhost.conf <<EOF -# Configure aliases -Alias /cache-manifest.cmf $here/htdocs/app/cache-manifest.cmf -Alias /data $here/htdocs/data -Alias /favicon.ico $here/htdocs/favicon.ico -Alias /footconfig.js $here/htdocs/footconfig.js -Alias /frame.html $here/htdocs/app/frame.html -Alias /headconfig.js $here/htdocs/headconfig.js -Alias /index.html $here/htdocs/app/index.html -Alias /login $here/htdocs/login -Alias /logout $here/htdocs/logout -Alias /notauth $here/htdocs/notauth -Alias /notfound $here/htdocs/notfound -Alias /notyet $here/htdocs/notyet -Alias /oops $here/htdocs/oops -Alias /public $here/htdocs/public -Alias /robots.txt $here/htdocs/robots.txt +# Configure app resource aliases +cat >>tmp/conf/svhost.conf <<EOF + +<Location /v> +RewriteEngine on + +# Map /v/<app-name>/<path> to htdocs/app/<path> +RewriteCond %{REQUEST_URI} ^/v/.+/.*$ +RewriteRule /v/(.+)/(.*)$ $here/htdocs/app/\$2 [L] + +# Redirect /v/<app-name> to /<app-name>/ +RewriteCond %{REQUEST_URI} ^/v/[^/]+$ +RewriteRule /v/([^/]+)$ /\$1/ [L,R] + +</Location> EOF diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf index 6c80e1a28f..085e2c6fa3 100755 --- a/sca-cpp/trunk/modules/http/httpd-conf +++ b/sca-cpp/trunk/modules/http/httpd-conf @@ -181,17 +181,11 @@ cat >$root/conf/mpm.conf <<EOF # Generated by: httpd-conf $* LoadModule mpm_prefork_module ${modules_prefix}/modules/mod_mpm_prefork.so -EOF - -uname=`uname -s` -if [ $uname = "Darwin" ]; then - cat >>$root/conf/mpm.conf <<EOF # Generated by: httpd-conf $* # Set thread stack size ThreadStackSize 2097152 EOF -fi # Generate modules list cat >$root/conf/modules.conf <<EOF diff --git a/sca-cpp/trunk/modules/http/httpd-event-conf b/sca-cpp/trunk/modules/http/httpd-event-conf index e4c89356db..a7cab03bc6 100755 --- a/sca-cpp/trunk/modules/http/httpd-event-conf +++ b/sca-cpp/trunk/modules/http/httpd-event-conf @@ -31,15 +31,9 @@ cat >$root/conf/mpm.conf <<EOF # Use HTTPD event MPM LoadModule mpm_event_module ${modules_prefix}/modules/mod_mpm_event.so -EOF - -uname=`uname -s` -if [ $uname = "Darwin" ]; then - cat >>$root/conf/mpm.conf <<EOF # Generated by: httpd-event-conf $* # Set thread stack size ThreadStackSize 2097152 EOF -fi diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf index 9de67ff716..9567c44cf1 100755 --- a/sca-cpp/trunk/modules/http/httpd-ssl-conf +++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf @@ -156,8 +156,8 @@ Include conf/vhost-ssl.conf # Declare SSL certificates used in this virtual host SSLCACertificateFile "$root/cert/ca.crt" SSLCertificateChainFile "$root/cert/ca.crt" -SSLCertificateFile "$root/cert/vhost.crt" -SSLCertificateKeyFile "$root/cert/vhost.key" +SSLCertificateFile "$root/cert/server.crt" +SSLCertificateKeyFile "$root/cert/server.key" # Declare proxy SSL client certificates SSLProxyCACertificateFile "$root/cert/ca.crt" diff --git a/sca-cpp/trunk/modules/http/httpd-worker-conf b/sca-cpp/trunk/modules/http/httpd-worker-conf index 74299085d8..84fe6b4a54 100755 --- a/sca-cpp/trunk/modules/http/httpd-worker-conf +++ b/sca-cpp/trunk/modules/http/httpd-worker-conf @@ -31,15 +31,9 @@ cat >$root/conf/mpm.conf <<EOF # Use HTTPD worker MPM LoadModule mpm_worker_module ${modules_prefix}/modules/mod_mpm_worker.so -EOF - -uname=`uname -s` -if [ $uname = "Darwin" ]; then - cat >>$root/conf/mpm.conf <<EOF # Generated by: httpd-event-conf $* # Set thread stack size ThreadStackSize 2097152 EOF -fi diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index 95cad7cf4f..d991f9aa61 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -580,7 +580,7 @@ sca.httpclient = function(name, uri, domain) { sca.component = function(name, domain) { if (!domain) return new HTTPBindingClient(name, '/c/' + name, domain); - return new HTTPBindingClient(name, '/a/' + domain + '/c/' + name, domain); + return new HTTPBindingClient(name, '/' + domain + '/c/' + name, domain); }; /** @@ -589,7 +589,7 @@ sca.component = function(name, domain) { sca.reference = function(comp, rname) { if (!comp.domain) return new HTTPBindingClient(comp.name + '/' + rname, '/r/' + comp.name + '/' + rname, comp.domain); - return new HTTPBindingClient(comp.name + '/' + rname, '/a/' + comp.domain + '/r/' + comp.name + '/' + rname, comp.domain); + return new HTTPBindingClient(comp.name + '/' + rname, '/' + comp.domain + '/r/' + comp.name + '/' + rname, comp.domain); }; /** diff --git a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt index 4395abf1dc..2cff8b7339 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt +++ b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt @@ -3,7 +3,7 @@ "result": { "host": "localhost", "path": [ - "components", + "c", "property-test" ], "query": { diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 00f59b9dda..b94636074a 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -26,6 +26,8 @@ * HTTPD module used to eval component implementations. */ +#include <sys/stat.h> + #include "string.hpp" #include "stream.hpp" #include "function.hpp" @@ -54,13 +56,15 @@ namespace modeval { */ class ServerConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s), wiringServerName(""), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(""), cert(""), key("") { + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(""), cert(""), key("") { + } + + ServerConf(apr_pool_t* p, const ServerConf& ssc, const string& name) : p(p), server(ssc.server), lifecycle(ssc.lifecycle), contributionPath(ssc.virtualHostContributionPath + name + "/"), compositeName(ssc.virtualHostCompositeName), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(ssc.ca), cert(ssc.cert), key(ssc.key) { } const gc_pool p; server_rec* server; lambda<value(const list<value>&)> lifecycle; - string wiringServerName; string contributionPath; string compositeName; string virtualHostContributionPath; @@ -119,7 +123,7 @@ public: /** * Handle an HTTP GET. */ -const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::get::uri"); // Inspect the query string @@ -145,8 +149,7 @@ const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& } // Evaluate the GET expression - const list<value> path(pathValues(r->uri)); - const list<value> params(append<value>(cddr(path), mkvalues(args))); + const list<value> params(append<value>(cddr(rpath), mkvalues(args))); const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(params)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -222,7 +225,7 @@ const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& /** * Handle an HTTP POST. */ -const failable<int> post(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> post(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::post::url"); // Evaluate a JSON-RPC request and return a JSON result @@ -257,7 +260,6 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> if (contains(ct, "application/atom+xml")) { // Read the ATOM entry - const list<value> path(pathValues(r->uri)); const int rc = httpd::setupReadPolicy(r); if(rc != OK) return rc; @@ -266,7 +268,7 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> const value entry = elementsToValues(content(atom::readATOMEntry(ls))); // Evaluate the POST expression - const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(cddr(path), entry)))); + const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(cddr(rpath), entry)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -288,11 +290,10 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> /** * Handle an HTTP PUT. */ -const failable<int> put(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> put(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::put::url"); // Read the ATOM entry - const list<value> path(pathValues(r->uri)); const int rc = httpd::setupReadPolicy(r); if(rc != OK) return rc; @@ -301,7 +302,7 @@ const failable<int> put(request_rec* r, const lambda<value(const list<value>&)>& const value entry = elementsToValues(content(atom::readATOMEntry(ls))); // Evaluate the PUT expression and update the corresponding resource - const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(path), entry)))); + const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(rpath), entry)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); if (val == value(false)) @@ -312,12 +313,11 @@ const failable<int> put(request_rec* r, const lambda<value(const list<value>&)>& /** * Handle an HTTP DELETE. */ -const failable<int> del(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> del(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::delete::url"); // Evaluate an ATOM delete request - const list<value> path(pathValues(r->uri)); - const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(cddr(path))))); + const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(cddr(rpath))))); if (!hasContent(val)) return mkfailure<int>(reason(val)); if (val == value(false)) @@ -328,13 +328,52 @@ const failable<int> del(request_rec* r, const lambda<value(const list<value>&)>& /** * Translate a component request. */ +const int translateRequest(const ServerConf& sc, const list<value>& rpath, request_rec *r) { + debug(rpath, "modeval::translateRequest::path"); + if (isNil(rpath)) + return DECLINED; + + // Translate a component request + const value c = car(rpath); + if (c == string("components") || c == string("c")) { + r->handler = "mod_tuscany_eval"; + return OK; + } + + // Translate a request targeting a virtual host or virtual app + if (hasVirtualCompositeConf(sc) && !isNil(cdr(rpath))) { + const string cp = sc.virtualHostContributionPath + string(c) + "/" + sc.virtualHostCompositeName; + struct stat st; + const int s = stat(c_str(cp), &st); + if (s != -1) { + const value d = cadr(rpath); + if (d == string("components") || d == string("c")) { + r->handler = "mod_tuscany_eval"; + return OK; + } + } + } + + return DECLINED; +} + +/** + * Translate a component request. + */ int translate(request_rec *r) { if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE) return DECLINED; - if (strncmp(r->uri, "/components/", 12) != 0 && strncmp(r->uri, "/c/", 3) != 0) - return DECLINED; - r->handler = "mod_tuscany_eval"; - return OK; + + // Create a scoped memory pool + gc_scoped_pool pool(r->pool); + + httpdDebugRequest(r, "modeval::translate::input"); + + // Get the server configuration + const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); + + // Translate the request + return translateRequest(sc, pathValues(r->uri), r); } /** @@ -473,7 +512,7 @@ const value mkunwiredProxy(const string& ref) { /** * Convert a list of component references to a list of proxy lambdas. */ -const value mkrefProxy(const ServerConf& sc, const value& ref, unused const string& base) { +const value mkrefProxy(const ServerConf& sc, const value& ref) { const value target = scdl::target(ref); const bool wbyimpl = scdl::wiredByImpl(ref); debug(ref, "modeval::mkrefProxy::ref"); @@ -490,10 +529,10 @@ const value mkrefProxy(const ServerConf& sc, const value& ref, unused const stri return mkimplProxy(sc, car(pathValues(target))); } -const list<value> refProxies(const ServerConf& sc, const list<value>& refs, const string& base) { +const list<value> refProxies(const ServerConf& sc, const list<value>& refs) { if (isNil(refs)) return refs; - return cons(mkrefProxy(sc, car(refs), base), refProxies(sc, cdr(refs), base)); + return cons(mkrefProxy(sc, car(refs)), refProxies(sc, cdr(refs))); } /** @@ -525,7 +564,8 @@ struct pathPropProxy { pathPropProxy(unused const value& v) { } const value operator()(unused const list<value>& params) const { - const value v = pathValues(currentRequest->uri); + const char* u = apr_table_get(currentRequest->headers_in, "X-Request-URI"); + const value v = u != NULL? pathValues(string(u)) : list<value>(); debug(v, "modeval::pathPropProxy::value"); return v; } @@ -624,9 +664,7 @@ const value evalComponent(ServerConf& sc, const value& comp) { debug(impl, "modeval::evalComponent::impl"); // Convert component references to configured proxy lambdas - ostringstream base; - base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/"; - const list<value> rpx(refProxies(sc, scdl::references(comp), str(base))); + const list<value> rpx(refProxies(sc, scdl::references(comp))); // Convert component properties to configured proxy lambdas const list<value> ppx(propProxies(scdl::properties(comp))); @@ -719,116 +757,93 @@ const failable<bool> startComponents(ServerConf& sc) { } /** - * Virtual host scoped server configuration. - */ -class VirtualHostConf { -public: - VirtualHostConf(const gc_pool& p, const ServerConf& sc) : sc(sc), vsc(pool(p), sc.server) { - vsc.lifecycle = sc.lifecycle; - vsc.virtualHostContributionPath = sc.virtualHostContributionPath; - vsc.virtualHostCompositeName = sc.virtualHostCompositeName; - vsc.ca = sc.ca; - vsc.cert = sc.cert; - vsc.key = sc.key; - } - - ~VirtualHostConf() { - extern const failable<bool> virtualHostCleanup(const ServerConf& vsc, const ServerConf& sc); - virtualHostCleanup(vsc, sc); - } - - const ServerConf& sc; - ServerConf vsc; -}; - -/** * Configure and start the components deployed in a virtual host. */ -const failable<bool> virtualHostConfig(ServerConf& vsc, const ServerConf& sc, request_rec* r) { - - // Determine the server name and wiring server name - debug(httpd::serverName(vsc.server), "modeval::virtualHostConfig::serverName"); +const failable<bool> virtualHostConfig(ServerConf& sc, const ServerConf& ssc, request_rec* r) { + debug(httpd::serverName(ssc.server), "modeval::virtualHostConfig::serverName"); debug(httpd::serverName(r), "modeval::virtualHostConfig::virtualHostName"); - vsc.wiringServerName = httpd::serverName(r); - debug(vsc.wiringServerName, "modeval::virtualHostConfig::wiringServerName"); - debug(vsc.virtualHostContributionPath, "modwiring::virtualHostConfig::virtualHostContributionPath"); - - // Resolve the configured virtual contribution under - // the virtual host's SCA contribution root - vsc.contributionPath = vsc.virtualHostContributionPath + http::subDomain(httpd::hostName(r)) + "/"; - vsc.compositeName = vsc.virtualHostCompositeName; + debug(ssc.virtualHostContributionPath, "modwiring::virtualHostConfig::virtualHostContributionPath"); + debug(sc.contributionPath, "modeval::virtualHostConfig::contributionPath"); // Chdir to the virtual host's contribution if (chdir(c_str(sc.contributionPath)) != 0) return mkfailure<bool>(string("Couldn't chdir to the deployed contribution: ") + sc.contributionPath); // Configure the deployed components - const failable<bool> cr = confComponents(vsc); + const failable<bool> cr = confComponents(sc); if (!hasContent(cr)) return cr; // Start the configured components - const failable<bool> sr = startComponents(vsc); + const failable<bool> sr = startComponents(sc); if (!hasContent(sr)) return sr; // Store the implementation lambda functions (from both the virtual host and the // main server) in a tree for fast retrieval - vsc.implTree = mkbtree(sort(append(vsc.implementations, sc.implementations))); + sc.implTree = mkbtree(sort(append(sc.implementations, ssc.implementations))); return true; } /** * Cleanup a virtual host. */ -const failable<bool> virtualHostCleanup(const ServerConf& vsc, const ServerConf& sc) { - if (!hasCompositeConf(vsc)) +const failable<bool> virtualHostCleanup(const ServerConf& sc, const ServerConf& ssc) { + if (!hasCompositeConf(sc)) return true; debug("modeval::virtualHostCleanup"); // Stop the component implementations - applyLifecycleExpr(vsc.implementations, mklist<value>("stop")); + applyLifecycleExpr(sc.implementations, mklist<value>("stop")); // Chdir back to the main server's contribution - if (chdir(c_str(sc.contributionPath)) != 0) - return mkfailure<bool>(string("Couldn't chdir to the deployed contribution: ") + sc.contributionPath); + if (chdir(c_str(ssc.contributionPath)) != 0) + return mkfailure<bool>(string("Couldn't chdir to the deployed contribution: ") + ssc.contributionPath); return true; } /** - * HTTP request handler. + * Handle a component request. */ -int handler(request_rec *r) { - if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE) - return DECLINED; - if(strcmp(r->handler, "mod_tuscany_eval")) - return DECLINED; - - // Create a scoped memory pool - gc_scoped_pool pool(r->pool); - - ScopedRequest sr(r); - httpdDebugRequest(r, "modeval::handler::input"); +const int handleRequest(const ServerConf& sc, const list<value>& rpath, request_rec *r) { + debug(rpath, "modeval::handleRequest::path"); + if (isNil(cdr(rpath))) + return HTTP_NOT_FOUND; - // Get the server configuration - const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); + // Handle a request targeting a virtual host or virtual app + if (hasVirtualCompositeConf(sc)) { + if (httpd::isVirtualHostRequest(sc.server, r)) { + ServerConf vsc(r->pool, sc, http::subDomain(httpd::hostName(r))); + if (!hasContent(virtualHostConfig(vsc, sc, r))) + return HTTP_INTERNAL_SERVER_ERROR; + const int rc = handleRequest(vsc, rpath, r); + virtualHostCleanup(vsc, sc); + return rc; + } - // Process dynamic virtual host configuration, if any - VirtualHostConf vhc(gc_pool(r->pool), sc); - const bool usevh = hasVirtualCompositeConf(vhc.vsc) && httpd::isVirtualHostRequest(sc.server, r); - if (usevh) { - const failable<bool> cr = virtualHostConfig(vhc.vsc, sc, r); - if (!hasContent(cr)) - return httpd::reportStatus(mkfailure<int>(reason(cr))); + const value c = car(rpath); + if (c != string("components") && c != string("c")) { + const string cp = sc.virtualHostContributionPath + string(c) + "/" + sc.virtualHostCompositeName; + struct stat st; + const int s = stat(c_str(cp), &st); + if (s != -1) { + ServerConf vsc(r->pool, sc, string(c)); + if (!hasContent(virtualHostConfig(vsc, sc, r))) + return HTTP_INTERNAL_SERVER_ERROR; + const int rc = handleRequest(vsc, cdr(rpath), r); + virtualHostCleanup(vsc, sc); + return rc; + } + } } + // Store the request uri path in a header + apr_table_setn(r->headers_in, "X-Request-URI", apr_pstrdup(r->pool, c_str(path(rpath)))); + // Get the component implementation lambda - const list<value> path(pathValues(r->uri)); - if (isNil(cdr(path))) - return HTTP_NOT_FOUND; - const list<value> impl(assoctree<value>(cadr(path), usevh? vhc.vsc.implTree : sc.implTree)); + const list<value> impl(assoctree<value>(cadr(rpath), sc.implTree)); if (isNil(impl)) { - mkfailure<int>(string("Couldn't find component implementation: ") + cadr(path)); + mkfailure<int>(string("Couldn't find component implementation: ") + cadr(rpath)); return HTTP_NOT_FOUND; } @@ -837,17 +852,39 @@ int handler(request_rec *r) { if (r->header_only) return OK; if(r->method_number == M_GET) - return httpd::reportStatus(get(r, l)); + return httpd::reportStatus(get(rpath, r, l)); if(r->method_number == M_POST) - return httpd::reportStatus(post(r, l)); + return httpd::reportStatus(post(rpath, r, l)); if(r->method_number == M_PUT) - return httpd::reportStatus(put(r, l)); + return httpd::reportStatus(put(rpath, r, l)); if(r->method_number == M_DELETE) - return httpd::reportStatus(del(r, l)); + return httpd::reportStatus(del(rpath, r, l)); return HTTP_NOT_IMPLEMENTED; } /** + * HTTP request handler. + */ +int handler(request_rec *r) { + if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE) + return DECLINED; + if(strcmp(r->handler, "mod_tuscany_eval")) + return DECLINED; + + // Create a scoped memory pool + 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); + + // Handle the request + return handleRequest(sc, pathValues(r->uri), r); +} + +/** * Cleanup callback, called when the server is stopped or restarted. */ apr_status_t serverCleanup(void* v) { @@ -876,9 +913,6 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) { return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval); debug(httpd::serverName(s), "modeval::postConfigMerge::serverName"); - if (sc.wiringServerName == "") - sc.wiringServerName = mainsc.wiringServerName != ""? mainsc.wiringServerName : httpd::serverName(s); - debug(sc.wiringServerName, "modeval::postConfigMerge::wiringServerName"); sc.lifecycle = mainsc.lifecycle; sc.contributionPath = mainsc.contributionPath; sc.compositeName = mainsc.compositeName; @@ -900,8 +934,6 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, // 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"); @@ -982,12 +1014,6 @@ void childInit(apr_pool_t* p, server_rec* s) { /** * Configuration commands. */ -const char* confWiringServerName(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.wiringServerName = arg; - return NULL; -} const char* confContribution(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); @@ -1040,7 +1066,6 @@ const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, con * HTTP server module declaration. */ 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"), diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index cb2f44c729..39e43c0420 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -57,6 +57,9 @@ public: ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName("") { } + ServerConf(apr_pool_t* p, const ServerConf& ssc, const string& name) : p(p), server(ssc.server), contributionPath(ssc.virtualHostContributionPath + name + "/"), compositeName(ssc.virtualHostCompositeName), virtualHostContributionPath(""), virtualHostCompositeName("") { + } + const gc_pool p; server_rec* server; string contributionPath; @@ -85,12 +88,13 @@ const bool hasVirtualCompositeConf(const ServerConf& sc) { * Route a /references/component-name/reference-name request, * to the target of the component reference. */ -int translateReference(const ServerConf& sc, request_rec *r) { +int translateReference(const ServerConf& sc, request_rec *r, const list<value>& rpath, const list<value>& apath) { httpdDebugRequest(r, "modwiring::translateReference::input"); debug(r->uri, "modwiring::translateReference::uri"); + debug(apath, "modwiring::translateReference::apath"); + debug(rpath, "modwiring::translateReference::rpath"); // Find the requested component - const list<value> rpath(pathValues(r->uri)); if (isNil(cdr(rpath))) return HTTP_NOT_FOUND; const list<value> comp(assoctree(cadr(rpath), sc.references)); @@ -110,8 +114,9 @@ int translateReference(const ServerConf& sc, request_rec *r) { if (useModProxy) { // Build proxy URI string turi = target + path(pathInfo) + (r->args != NULL? string("?") + r->args : string("")); - r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + turi)); - debug(r->filename, "modwiring::translateReference::filename"); + const string proxy(string("proxy:") + turi); + debug(proxy, "modwiring::translateReference::proxy"); + r->filename = apr_pstrdup(r->pool, c_str(proxy)); r->proxyreq = PROXYREQ_REVERSE; r->handler = "proxy-server"; apr_table_setn(r->notes, "proxy-nocanon", "1"); @@ -126,9 +131,10 @@ int translateReference(const ServerConf& sc, request_rec *r) { // Route to a relative target URI using a local internal redirect // /components/, target component name and request path info const value tname = substr(target, 0, find(target, '/')); - const string tpath = path(cons(tname, pathInfo)) + (r->args != NULL? string("?") + r->args : string("")); - r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/components") + tpath)); - debug(r->filename, "modwiring::translateReference::filename"); + const string tp = path(append(apath, cons<value>(string("c"), cons(tname, pathInfo)))) + (r->args != NULL? string("?") + r->args : string("")); + const string redir(string("/redirect:") + tp); + debug(redir, "modwiring::translateReference::redirect"); + r->filename = apr_pstrdup(r->pool, c_str(redir)); r->handler = "mod_tuscany_wiring"; return OK; } @@ -159,26 +165,24 @@ const list<value> assocPath(const value& k, const list<value>& tree) { /** * Route a service request to the component providing the requested service. */ -int translateService(const ServerConf& sc, request_rec *r) { +int translateService(const ServerConf& sc, request_rec *r, const list<value>& rpath, const list<value>& apath) { httpdDebugRequest(r, "modwiring::translateService::input"); debug(r->uri, "modwiring::translateService::uri"); // Find the requested component debug(sc.services, "modwiring::translateService::services"); - const list<value> p(pathValues(r->uri)); - const list<value> svc(assocPath(p, sc.services)); + const list<value> svc(assocPath(rpath, sc.services)); if (isNil(svc)) return DECLINED; debug(svc, "modwiring::translateService::service"); // Build a component-name + path-info URI - const list<value> target(cons<value>(cadr(svc), httpd::pathInfo(p, car(svc)))); + const list<value> target(append(apath, cons<value>(string("c"), cons<value>(cadr(svc), httpd::pathInfo(rpath, car(svc)))))); debug(target, "modwiring::translateService::target"); // Dispatch to the target component using a local internal redirect - const string tp(path(target)); - debug(tp, "modwiring::translateService::path"); - const string redir(string("/redirect:/components") + tp); + const string tp(path(target) + (r->args != NULL? string("?") + r->args : string(""))); + const string redir(string("/redirect:") + tp); debug(redir, "modwiring::translateService::redirect"); r->filename = apr_pstrdup(r->pool, c_str(redir)); r->handler = "mod_tuscany_wiring"; @@ -186,38 +190,6 @@ int translateService(const ServerConf& sc, request_rec *r) { } /** - * Route an /apps/app-name/... request to the target app domain. - */ -int translateDomain(request_rec *r) { - httpdDebugRequest(r, "modwiring::translateDomain::input"); - debug(r->uri, "modwiring::translateDomain::uri"); - - // Extract the requested app name - const list<value> apath(pathValues(r->uri)); - if (isNil(cdr(apath))) - return HTTP_NOT_FOUND; - - // Compute the target uri in the target app domain - ostringstream turi; - turi << httpd::scheme(r) << "://" << string(cadr(apath)) << "." << httpd::hostName(r) << ":" << httpd::port(r) << string(path(cddr(apath))) << (r->args != NULL? string("?") + r->args : string("")); - debug(str(turi), "modwiring::translateDomain::appuri"); - - // Route to an absolute target URI using mod_proxy or an HTTP client redirect - if (useModProxy) { - r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + str(turi))); - debug(r->filename, "modwiring::translateDomain::filename"); - r->proxyreq = PROXYREQ_REVERSE; - r->handler = "proxy-server"; - apr_table_setn(r->notes, "proxy-nocanon", "1"); - return OK; - } - - debug(str(turi), "modwiring::translateDomain::location"); - r->handler = "mod_tuscany_wiring"; - return httpd::externalRedirect(str(turi), r); -} - -/** * Read the components declared in a composite. */ const failable<list<value> > readComponents(const string& path) { @@ -299,37 +271,83 @@ const bool confComponents(ServerConf& sc) { } /** - * Virtual host scoped server configuration. + * Configure and start the components deployed in a virtual host. */ -class VirtualHostConf { -public: - VirtualHostConf(const gc_pool& p, const ServerConf& ssc) : sc(pool(p), ssc.server) { - sc.virtualHostContributionPath = ssc.virtualHostContributionPath; - sc.virtualHostCompositeName = ssc.virtualHostCompositeName; - } +const failable<ServerConf> virtualHostConfig(ServerConf& sc, const ServerConf& ssc, request_rec* r) { + debug(httpd::serverName(ssc.server), "modwiring::virtualHostConfig::serverName"); + debug(httpd::serverName(r), "modwiring::virtualHostConfig::virtualHostName"); + debug(ssc.virtualHostContributionPath, "modwiring::virtualHostConfig::virtualHostContributionPath"); + debug(sc.contributionPath, "modwiring::virtualHostConfig::contributionPath"); - ~VirtualHostConf() { - } + // Configure the wiring for the deployed components + confComponents(sc); - ServerConf sc; -}; + return sc; +} /** - * Configure and start the components deployed in a virtual host. + * Translate an HTTP service or reference request and route it + * to the target component. */ -const failable<bool> virtualHostConfig(ServerConf& sc, request_rec* r) { - debug(httpd::serverName(sc.server), "modwiring::virtualHostConfig::serverName"); - debug(httpd::serverName(r), "modwiring::virtualHostConfig::virtualHostName"); - debug(sc.virtualHostContributionPath, "modwiring::virtualHostConfig::virtualHostContributionPath"); +const int translateRequest(const ServerConf& sc, request_rec *r, const list<value>& rpath, const list<value>& apath) { + debug(apath, "modwiring::translateRequest::apath"); + debug(rpath, "modwiring::translateRequest::rpath"); + if (isNil(apath) && isNil(rpath)) + return DECLINED; - // Resolve the configured virtual contribution under - // the virtual host's SCA contribution root - sc.contributionPath = sc.virtualHostContributionPath + http::subDomain(httpd::hostName(r)) + "/"; - sc.compositeName = sc.virtualHostCompositeName; + if (!isNil(rpath)) { + + // No translation needed for a component or resource request + const value c = car(rpath); + if (c == string("components") || c == string("c") || c == string("vhosts") || c == string("v")) + return DECLINED; + + // If the request is targeting a virtual host, use the corresponding + // virtual host configuration + const bool vcc = hasVirtualCompositeConf(sc); + if (vcc && httpd::isVirtualHostRequest(sc.server, r)) { + ServerConf vsc(r->pool, sc, http::subDomain(httpd::hostName(r))); + if (!hasContent(virtualHostConfig(vsc, sc, r))) + return HTTP_INTERNAL_SERVER_ERROR; + return translateRequest(vsc, r, rpath, list<value>()); + } - // Configure the wiring for the deployed components - confComponents(sc); - return true; + // Translate a component reference request + if (c == string("references") || c == string("r")) + return translateReference(sc, r, rpath, apath); + + // Attempt to translate the request to a service request + if (translateService(sc, r, rpath, apath) == OK) + return OK; + + // If the request is targeting a virtual app, use the corresponding + // virtual host configuration + if (vcc) { + const string cp = sc.virtualHostContributionPath + string(c) + "/" + sc.virtualHostCompositeName; + struct stat st; + const int s = stat(c_str(cp), &st); + if (s == -1) + return DECLINED; + ServerConf vsc(r->pool, sc, string(c)); + if (!hasContent(virtualHostConfig(vsc, sc, r))) + return HTTP_INTERNAL_SERVER_ERROR; + return translateRequest(vsc, r, cdr(rpath), mklist<value>(car(rpath))); + } + } + + // If we're in a virtual app and the request is targeting a regular + // resource, redirect it to /v/<uri>. This will allow mapping to the + // actual resources using HTTPD aliases. + if (!isNil(apath)) { + const string tp = string("/v") + string(r->uri) + (r->args != NULL? string("?") + r->args : string("")); + const string redir = string("/redirect:") + tp; + debug(redir, "modwiring::translateRequest::redirect"); + r->filename = apr_pstrdup(r->pool, c_str(redir)); + r->handler = "mod_tuscany_wiring"; + return OK; + } + + return DECLINED; } /** @@ -340,35 +358,15 @@ int translate(request_rec *r) { if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE) return DECLINED; - // No translation needed for a component or tunnel request - if (!strncmp(r->uri, "/components/", 12) || !strncmp(r->uri, "/c/", 3)) - return DECLINED; - // Create a scoped memory pool gc_scoped_pool pool(r->pool); - - // Translate an app domain request - if (!strncmp(r->uri, "/apps/", 6) || !strncmp(r->uri, "/a/", 3)) - return translateDomain(r); + httpdDebugRequest(r, "modwiring::translate::input"); // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring); - // Process dynamic virtual host configuration - VirtualHostConf vhc(gc_pool(r->pool), sc); - const bool usevh = hasVirtualCompositeConf(vhc.sc) && httpd::isVirtualHostRequest(sc.server, r); - if (usevh) { - const failable<bool> cr = virtualHostConfig(vhc.sc, r); - if (!hasContent(cr)) - return -1; - } - - // Translate a component reference request - if (!strncmp(r->uri, "/references/", 12) || !strncmp(r->uri, "/r/", 3)) - return translateReference(usevh? vhc.sc: sc, r); - - // Translate a service request - return translateService(usevh? vhc.sc : sc, r); + // Translate the request + return translateRequest(sc, r, pathValues(r->uri), list<value>()); } /** @@ -389,12 +387,12 @@ int handler(request_rec *r) { // Create a scoped memory pool gc_scoped_pool pool(r->pool); - // Do an internal redirect httpdDebugRequest(r, "modwiring::handler::input"); - debug(r->uri, "modwiring::handler::uri"); debug(r->filename, "modwiring::handler::filename"); debug(r->path_info, "modwiring::handler::path info"); + + // Do an internal redirect 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); diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf index a8e57cf289..5b3024abbc 100755 --- a/sca-cpp/trunk/modules/server/server-conf +++ b/sca-cpp/trunk/modules/server/server-conf @@ -31,25 +31,6 @@ else libsuffix=".so" fi -conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` -host=`echo $conf | awk '{ print $6 }'` -port=`echo $conf | awk '{ print $7 }' | awk -F "/" '{ print $1 }'` -pport=`echo $conf | awk '{ print $7 }' | awk -F "/" '{ print $2 }'` -if [ "$pport" = "" ]; then - pport=$port -fi -servername="http://$host:$pport" - -sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"` -if [ "$sslconf" != "" ]; then - sslport=`echo $sslconf | awk '{ print $6 }' | awk -F "/" '{ print $1 }'` - sslpport=`echo $sslconf | awk '{ print $6 }' | awk -F "/" '{ print $2 }'` - if [ "$sslpport" = "" ]; then - sslpport=$sslport - fi - servername="https://$host:$sslpport" -fi - cat >>$root/conf/modules.conf <<EOF # Generated by: server-conf $* # Support for SCA component wiring @@ -59,9 +40,6 @@ EOF cat >>$root/conf/httpd.conf <<EOF # Generated by: server-conf $* -# Route all wiring through the configured server name -SCAWiringServerName $servername - # Serve JavaScript client scripts Alias /component.js $jsprefix/htdocs/component.js Alias /util.js $jsprefix/htdocs/util.js |