summaryrefslogtreecommitdiffstats
path: root/cpp/sca/modules/http/mod-wiring.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cpp/sca/modules/http/mod-wiring.cpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/cpp/sca/modules/http/mod-wiring.cpp b/cpp/sca/modules/http/mod-wiring.cpp
new file mode 100644
index 0000000000..965d5a87fb
--- /dev/null
+++ b/cpp/sca/modules/http/mod-wiring.cpp
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * HTTPD module used to wire components.
+ */
+
+#include <sys/stat.h>
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+#include "list.hpp"
+#include "slist.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "../scdl/scdl.hpp"
+#include "../cache/cache.hpp"
+#include "httpd.hpp"
+
+extern "C" {
+extern module AP_MODULE_DECLARE_DATA mod_tuscany_wiring;
+}
+
+namespace tuscany {
+namespace httpd {
+namespace modwiring {
+
+/**
+ * Server configuration.
+ */
+class ServerConf {
+public:
+ std::string home;
+ ServerConf() : home("") {
+ }
+};
+
+const ServerConf& serverConf(const request_rec* r) {
+ return *(ServerConf*)ap_get_module_config(r->server->module_config, &mod_tuscany_wiring);
+}
+
+/**
+ * Set to true to wire using mod_proxy, false to wire using HTTP client redirects.
+ */
+const bool useModProxy = true;
+
+/**
+ * Directory configuration.
+ */
+class DirConf {
+public:
+ DirConf() : contributionPath(""), compositeName("") {
+ }
+ std::string contributionPath;
+ std::string compositeName;
+ cache::cached<failable<list<value>, std::string> > components;
+};
+
+DirConf& dirConf(const request_rec* r) {
+ return *(DirConf*)ap_get_module_config(r->per_dir_config, &mod_tuscany_wiring);
+}
+
+/**
+ * Read the SCDL configuration of the deployed components.
+ */
+const failable<list<value>, std::string> readComponents(const std::string& path) {
+ std::ifstream is(path);
+ if (is.fail() || is.bad())
+ return mkfailure<list<value>, std::string>("Could not read composite: " + path);
+ return scdl::components(readXML(streamList(is)));
+}
+
+const cache::cached<failable<list<value>, std::string> > components(DirConf* conf) {
+ const std::string path(conf->contributionPath + conf->compositeName);
+ const lambda<failable<list<value>, std::string>(std::string)> rc(readComponents);
+ const lambda<unsigned long(std::string)> ft(cache::latestFileTime);
+ return cache::cached<failable<list<value>, std::string> >(curry(rc, path), curry(ft, path));
+}
+
+/**
+ * Returns true if a URI is absolute.
+ */
+const bool isAbsolute(const std::string& uri) {
+ return uri.find("://") != std::string::npos;
+}
+
+/**
+ * Translate an HTTP request URI. Wire a URI in the form /references/component-name/reference-name
+ * to the target of the reference.
+ */
+int translate(request_rec *r) {
+ if (strncmp(r->uri, "/references/", 12) != 0)
+ return DECLINED;
+ const list<value> rpath(path(r->uri));
+
+ // Log the request
+ if(logRequests)
+ logRequest(r, "mod_tuscany_wiring::translate");
+
+ // Find the requested component, reference and its target configuration
+ DirConf& conf = dirConf(r);
+ conf.components = cache::latest(conf.components);
+ const failable<list<value>, std::string> comps(conf.components);
+ if (!hasValue(comps))
+ return HTTP_INTERNAL_SERVER_ERROR;
+ const value comp(scdl::named(cadr(rpath), list<value>(comps)));
+ if (isNil(comp))
+ return HTTP_NOT_FOUND;
+ const value ref(scdl::named(caddr(rpath), scdl::references(comp)));
+ if (isNil(ref))
+ return HTTP_NOT_FOUND;
+ const std::string target(scdl::target(ref));
+
+ // Absolute target URI
+ if (isAbsolute(target)) {
+
+ // Wire using mod_proxy
+ if (useModProxy) {
+ r->filename = apr_pstrdup(r->pool, std::string("proxy:" + target).c_str());
+ r->proxyreq = PROXYREQ_REVERSE;
+ r->handler = "proxy-server";
+ return OK;
+ }
+
+ // Wire using an HTTP client redirect
+ r->status = HTTP_MOVED_TEMPORARILY;
+ apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, target.c_str()));
+ r->handler = "mod_tuscany_wiring";
+ return OK;
+
+ }
+
+ // Local internal redirect
+ r->filename = apr_pstrdup(r->pool, std::string("/redirect:/" + target).c_str());
+ r->handler = "mod_tuscany_wiring";
+ return OK;
+}
+
+/**
+ * Construct a redirect URI.
+ */
+const std::string redirect(const std::string& file, const std::string& pi) {
+ return file + pi;
+}
+
+const std::string redirect(const std::string& file, const std::string& pi, const std::string& args) {
+ return file + pi + "?" + args;
+}
+
+/**
+ * HTTP request internal redirect handler.
+ */
+int handler(request_rec *r) {
+ if(strcmp(r->handler, "mod_tuscany_wiring"))
+ return DECLINED;
+
+ // Log the request
+ if(logRequests)
+ logRequest(r, "mod_tuscany_wiring::handler");
+
+ // Do an internal redirect
+ if (r->filename == NULL || strncmp(r->filename, "/redirect:", 10) != 0)
+ return DECLINED;
+ if (r->args == NULL) {
+ ap_internal_redirect(apr_pstrdup(r->pool, redirect(r->filename + 10, r->path_info).c_str()), r);
+ return OK;
+ }
+ ap_internal_redirect(apr_pstrdup(r->pool, redirect(r->filename + 10, r->path_info, r->args).c_str()), r);
+ return OK;
+}
+
+/**
+ * Configuration commands.
+ */
+const char *confHome(cmd_parms *cmd, void *dummy, const char *arg) {
+ ServerConf *c = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany_wiring);
+ c->home = arg;
+ return NULL;
+}
+const char *confContribution(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf* conf = (DirConf*)c;
+ conf->contributionPath = arg;
+ conf->components = components(conf);
+ return NULL;
+}
+const char *confComposite(cmd_parms *cmd, void *c, const char *arg) {
+ DirConf* conf = (DirConf*)c;
+ conf->compositeName = arg;
+ conf->components = components(conf);
+ return NULL;
+}
+
+void *makeDirConf(apr_pool_t *p, char *dirspec) {
+ DirConf* c = new (apr_palloc(p, sizeof(DirConf))) DirConf();
+ apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback<DirConf>, apr_pool_cleanup_null) ;
+ return c;
+}
+void* makeServerConf(apr_pool_t *p, server_rec *s) {
+ ServerConf* c = new (apr_palloc(p, sizeof(ServerConf))) ServerConf();
+ apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback<ServerConf>, apr_pool_cleanup_null) ;
+ return c;
+}
+
+/**
+ * HTTP server module declaration.
+ */
+const command_rec commands[] = {
+ AP_INIT_TAKE1("TuscanyHome", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"),
+ AP_INIT_TAKE1("SCAContribution", (const char*(*)())confContribution, NULL, ACCESS_CONF, "SCA contribution location"),
+ AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, ACCESS_CONF, "SCA composite location"),
+ {NULL}
+};
+
+int postConfig(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
+ return OK;
+}
+
+void childInit(apr_pool_t* p, server_rec* svr_rec) {
+ ServerConf *conf = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_wiring);
+ if(conf == NULL) {
+ std::cerr << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << std::endl;
+ exit(APEXIT_CHILDFATAL);
+ }
+}
+
+void registerHooks(apr_pool_t *p) {
+ ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_translate_name(translate, NULL, NULL, APR_HOOK_FIRST);
+}
+
+}
+}
+}
+
+extern "C" {
+
+module AP_MODULE_DECLARE_DATA mod_tuscany_wiring = {
+ STANDARD20_MODULE_STUFF,
+ // dir config
+ tuscany::httpd::modwiring::makeDirConf,
+ // dir merger, default is to override
+ NULL,
+ // server config
+ tuscany::httpd::modwiring::makeServerConf,
+ // merge server config
+ NULL,
+ // command table
+ tuscany::httpd::modwiring::commands,
+ // register hooks
+ tuscany::httpd::modwiring::registerHooks
+};
+
+}