diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-30 08:06:00 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-30 08:06:00 +0000 |
commit | c06d7a38b904247917462c3c1a780f95c68e0709 (patch) | |
tree | 09e734786aa4aa710b7248921185f9ace9454078 /sca-cpp | |
parent | eb644871fca453fbc7de6dc6746eade97cb3a848 (diff) |
Added a Web service listener component integrating Axis2/C's mod_axis2. Consolidated a bit the HTTPD redirect functions (used to redirect to mod_axis2.) Minor updates to the README and INSTALL files.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@904733 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp')
21 files changed, 804 insertions, 60 deletions
diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL index 5dff8031dc..aaad7a0b30 100644 --- a/sca-cpp/trunk/INSTALL +++ b/sca-cpp/trunk/INSTALL @@ -25,10 +25,6 @@ httpd-2.2-13 libapr-1-0.3.8 libaprutil-1-0.3.9 -Recommended HTTPD configure options: ---with-included-apr to build HTTPD with the included APR distribution, ---with-mpm=worker to run HTTPD modules in multiple threads. - XML libxml2-2.7.5 @@ -39,11 +35,11 @@ JSON SpiderMonkey libmozjs (included in xulrunner-1.9.1.7) -Python (optional) -libpython2.6 +Optional dependencies: -Java (optional) -a Java 6 development kit including jni.h and libjava +Axis2/C 1.6.0 +Python 2.6 +a Java 6 SDK To configure the Tuscany SCA build do this: @@ -88,7 +84,7 @@ installed under $HOME: --enable-python --with-python=/usr \ --enable-java --with-java=/usr/lib/jvm/default-java \ --enable-webservice --with-axis2c=$HOME/axis2c-1.6.0-bin \ ---enable-threads --enable-maintainer-mode +--enable-maintainer-mode To build the Tuscany SCA runtime, do this: @@ -113,3 +109,21 @@ Installing To install the Tuscany SCA binaries, do this: make install + +Building dependencies from source +================================= + +Here are example build and install steps for HTTPD (including APR) and Axis2/C: + +./configure --enable-ssl --enable-proxy --enable-rewrite --with-included-apr \ +--with-mpm=prefork --prefix=$HOME/httpd-2.2.13-bin +make +make install +export PATH=$HOME/httpd-2-2.13-bin/bin:$PATH + +./configure --enable-libxml2 --enable-openssl --enable-libcurl \ +--with-apache2=$HOME/httpd-2.2.13-bin/include --prefix=$HOME/axis2c-1.6.0-bin +make +make install +export AXIS2C_HOME=$HOME/axis2c-1.6.0-bin + diff --git a/sca-cpp/trunk/README b/sca-cpp/trunk/README index c3a0999d92..7869d70b09 100644 --- a/sca-cpp/trunk/README +++ b/sca-cpp/trunk/README @@ -36,12 +36,16 @@ Here's a rough guide to the Tuscany SCA source tree: | | |-- java Support for Java components | | |-- python Support for Python components | | |-- scheme Support for Scheme components - | | |-- server HTTPD server integration + | | |-- server Apache HTTPD server integration + | | |-- xmpp XMPP protocol support | | | |-- components Useful SCA components - | | |-- cache Memcached-based cache component - | | |-- store Persistent store component - | | |-- webservice Web service gateway component using Axis2C + | | |-- cache Key/value cache (requires Memcached) + | | |-- chat XMPP chat + | | |-- log Logger + | | |-- queue AMQP message queue (requires Apache Qpid/C++) + | | |-- store Persistent store + | | |-- webservice Web service gateway (requires Apache Axis2/C) | | | |-- test Integration tests | | diff --git a/sca-cpp/trunk/components/webservice/Makefile.am b/sca-cpp/trunk/components/webservice/Makefile.am index 8d6a9a7879..b12518076b 100644 --- a/sca-cpp/trunk/components/webservice/Makefile.am +++ b/sca-cpp/trunk/components/webservice/Makefile.am @@ -22,7 +22,7 @@ noinst_PROGRAMS = axiom-test axis2-test client-test INCLUDES = -I${AXIS2C_INCLUDE} compdir=$(prefix)/components/webservice -comp_LTLIBRARIES = libwebservice-client.la libwebservice-listener.la +comp_LTLIBRARIES = libwebservice-client.la libwebservice-listener.la libaxis2-dispatcher.la libaxis2-service.la libwebservice_client_la_SOURCES = webservice-client.cpp libwebservice_client_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine @@ -30,6 +30,12 @@ libwebservice_client_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2 libwebservice_listener_la_SOURCES = webservice-listener.cpp libwebservice_listener_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine +libaxis2_dispatcher_la_SOURCES = axis2-dispatcher.cpp +libaxis2_dispatcher_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine + +libaxis2_service_la_SOURCES = axis2-service.cpp +libaxis2_service_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine + axiom_test_SOURCES = axiom-test.cpp axiom_test_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine @@ -37,7 +43,7 @@ axis2_test_SOURCES = axis2-test.cpp axis2_test_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine TESTS = axiom-test echo-test server-test diff --git a/sca-cpp/trunk/components/webservice/axis2-conf b/sca-cpp/trunk/components/webservice/axis2-conf new file mode 100755 index 0000000000..28f8a0be94 --- /dev/null +++ b/sca-cpp/trunk/components/webservice/axis2-conf @@ -0,0 +1,51 @@ +#!/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. + +# Generate an Axis2 server conf +here=`readlink -f $0`; here=`dirname $here` +root=`readlink -f $1` + +# Create an Axis2 home directory +mkdir -p $root/axis2c +ln -f -s $AXIS2C_HOME/lib $root/axis2c/lib +mkdir -p $root/axis2c/logs +mkdir -p $root/axis2c/modules +ln -f -s $AXIS2C_HOME/modules/addressing $root/axis2c/modules/addressing +ln -f -s $AXIS2C_HOME/modules/logging $root/axis2c/modules/logging +mkdir -p $root/axis2c/services + +# Install Tuscany Axis2 module and service +mkdir -p $root/axis2c/modules/tuscany +ln -f -s $here/.libs/libaxis2-dispatcher.so $root/axis2c/modules/tuscany/libaxis2-dispatcher.so +ln -f -s $here/module.xml $root/axis2c/modules/tuscany/module.xml +mkdir -p $root/axis2c/services/tuscany +ln -f -s $here/.libs/libaxis2-service.so $root/axis2c/services/tuscany/libaxis2-service.so +ln -f -s $here/services.xml $root/axis2c/services/tuscany/services.xml +cp $here/axis2.xml $root/axis2c/axis2.xml + +# Configure HTTPD Axis2 module +cat >>$root/conf/httpd.conf <<EOF +LoadModule axis2_module $root/axis2c/lib/libmod_axis2.so +Axis2RepoPath $root/axis2c +Axis2LogFile $root/axis2c/logs/mod_axis2.log +Axis2LogLevel debug +<Location /axis2> + SetHandler axis2_module +</Location> +EOF diff --git a/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp b/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp new file mode 100644 index 0000000000..3f753e0e35 --- /dev/null +++ b/sca-cpp/trunk/components/webservice/axis2-dispatcher.cpp @@ -0,0 +1,138 @@ +/* + * 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$ */ + +/** + * Axis2/C module that dispatches all server requests to the Tuscany Axis/2C service. + */ + +#include "axis2.hpp" + +namespace tuscany { +namespace webservice { + +/** + * Determine the service and operation to dispatch a request to. + */ +axis2_svc_t* AXIS2_CALL dispatchFindService(axis2_msg_ctx_t* msg_ctx, const axutil_env_t* env) { + const axis2_conf_ctx_t* conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + const axis2_conf_t* conf = axis2_conf_ctx_get_conf(conf_ctx, env); + axis2_svc_t* svc = axis2_conf_get_svc(conf, env, "TuscanyService"); + return svc; +} + +axis2_op_t *AXIS2_CALL dispatchFindOp(unused axis2_msg_ctx_t* msg_ctx, const axutil_env_t* env, axis2_svc_t* svc) { + axutil_qname_t* op_qname = axutil_qname_create(env, "execute", NULL, NULL); + axis2_op_t *op = axis2_svc_get_op_with_name(svc, env, axutil_qname_get_localpart(op_qname, env)); + axutil_qname_free(op_qname, env); + return op; +} + +/** + * Dispatcher invoke function, called by Axis2/C. + */ +axis2_status_t AXIS2_CALL dispatchInvoke( struct axis2_handler* handler, const axutil_env_t* env, axis2_msg_ctx_t* msg_ctx) { + if (!(axis2_msg_ctx_get_server_side(msg_ctx, env))) + return AXIS2_SUCCESS; + axis2_msg_ctx_set_find_svc(msg_ctx, env, dispatchFindService); + axis2_msg_ctx_set_find_op(msg_ctx, env, dispatchFindOp); + return axis2_disp_find_svc_and_op(handler, env, msg_ctx); +} + +/** + * Create a dispatch handler. + */ +AXIS2_EXPORT axis2_handler_t* AXIS2_CALL dispatchHandler(const axutil_env_t* env, unused axutil_string_t* name) { + axis2_handler_t *handler = axis2_handler_create(env); + if (handler == NULL) + return NULL; + axis2_handler_set_invoke(handler, env, dispatchInvoke); + return handler; +} + +/** + * Initialize dispatch module. + */ +axis2_status_t AXIS2_CALL dispatchInit(unused axis2_module_t * module, unused const axutil_env_t * env, unused axis2_conf_ctx_t * conf_ctx, unused axis2_module_desc_t * module_desc) { + return AXIS2_SUCCESS; +} + +/** + * Initialize dispatch module function map. + */ +axis2_status_t AXIS2_CALL dispatchFuncMap(axis2_module_t * module, const axutil_env_t * env) { + module->handler_create_func_map = axutil_hash_make(env); + axutil_hash_set(module->handler_create_func_map, "TuscanyDispatcher", AXIS2_HASH_KEY_STRING, (const void *)dispatchHandler); + return AXIS2_SUCCESS; +} + +/** + * Shutdown dispatch module. + */ +axis2_status_t AXIS2_CALL dispatchShutdown(axis2_module_t* module, const axutil_env_t* env) { + if (module->handler_create_func_map != NULL) { + axutil_hash_free(module->handler_create_func_map, env); + module->handler_create_func_map = NULL; + } + AXIS2_FREE(env->allocator, module); + return AXIS2_SUCCESS; +} + +/** + * Return a new dispatch module. + */ +const axis2_module_ops_t dispatchOps = { + dispatchInit, + dispatchShutdown, + dispatchFuncMap +}; + +axis2_module_t * dispatchModule(const axutil_env_t* env) { + axis2_module_t *module = (axis2_module_t*)AXIS2_MALLOC(env->allocator, sizeof(axis2_module_t)); + if (module == NULL) + return NULL; + module->ops = &dispatchOps; + module->handler_create_func_map = NULL; + return module; +} + +} +} + +extern "C" +{ + +/** + * Axis2/C module entry point functions. + */ +AXIS2_EXPORT int axis2_get_instance(axis2_module_t** inst, const axutil_env_t* env) { + *inst = tuscany::webservice::dispatchModule(env); + if(*inst == NULL) + return AXIS2_FAILURE; + return AXIS2_SUCCESS; +} + +AXIS2_EXPORT int axis2_remove_instance(axis2_module_t* inst, const axutil_env_t* env) { + if (inst != NULL) + return tuscany::webservice::dispatchShutdown(inst, env); + return AXIS2_FAILURE; +} + +} diff --git a/sca-cpp/trunk/components/webservice/axis2-service.cpp b/sca-cpp/trunk/components/webservice/axis2-service.cpp new file mode 100644 index 0000000000..4c0ce22722 --- /dev/null +++ b/sca-cpp/trunk/components/webservice/axis2-service.cpp @@ -0,0 +1,151 @@ +/* + * 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$ */ + +/** + * Axis2/C service implementation that dispatches requests to SCA Web service components. + */ + +#include "value.hpp" +#include "string.hpp" +#include "../../modules/http/httpd.hpp" +#include "axis2.hpp" + +namespace tuscany { +namespace webservice { + +/** + * Initialize the service. + */ +int AXIS2_CALL serviceInit(unused axis2_svc_skeleton_t* svc_skeleton, unused const axutil_env_t* env) { + return AXIS2_SUCCESS; +} + +/** + * Free the service. + */ +int AXIS2_CALL serviceFree(axis2_svc_skeleton_t* svc_skeleton, const axutil_env_t* env) { + if (svc_skeleton) + AXIS2_FREE(env->allocator, svc_skeleton); + return AXIS2_SUCCESS; +} + +typedef struct axis2_apache2_out_transport_info { + axis2_http_out_transport_info_t out_transport_info; + request_rec *request; + axis2_char_t *encoding; +} axis2_apache2_out_transport_info_t; + +extern "C" { + extern module axis2_module; +} + +/** + * Service invoke function, called by Axis2/C. + */ +axiom_node_t *AXIS2_CALL serviceInvoke(unused axis2_svc_skeleton_t* svc_skeleton, const axutil_env_t* env, axiom_node_t* node, axis2_msg_ctx_t* msg_ctx) { + + // Check that we have an input node + if (node == NULL || axiom_node_get_node_type(node, env) != AXIOM_ELEMENT) + return NULL; + axiom_element_t *e = (axiom_element_t *) axiom_node_get_data_element(node, env); + if (e == NULL) + return NULL; + + // Get the function name + const char* func = axiom_element_get_localname(e, env); + if (func == NULL) + return NULL; + + // Get the target endpoint address + const axis2_endpoint_ref_t* epr = axis2_msg_ctx_get_from(msg_ctx, env); + if (epr == NULL) + return NULL; + string address = axis2_endpoint_ref_get_address(epr, env); + + // Get the underlying HTTPD request + axis2_out_transport_info_t* tinfo = axis2_msg_ctx_get_out_transport_info(msg_ctx, env); + axis2_apache2_out_transport_info_t* httpinfo = (axis2_apache2_out_transport_info_t*)tinfo; + request_rec* r = httpinfo->request; + httpdDebugRequest(r, "webservice::serviceInvoke"); + + // Parse the request Axiom node and construct request expression + Axis2Context ax(env); + const failable<const list<value> > lv = axiomNodeToValues(node, ax); + if (!hasContent(lv)) + return NULL; + const value expr = mklist<value>(func, content(lv)); + debug(expr, "webservice::serviceInvoke::expr"); + + // Retrieve the target lambda function from the HTTPD request and invoke it + const value* rv = const_cast<const value*>((value*)ap_get_module_config(r->request_config, &axis2_module)); + cout << "relay: " << rv << endl; + const lambda<value(const list<value>&)> relay = *rv; + const value res = relay(expr); + debug(res, "webservice::serviceInvoke::result"); + + // Construct response Axiom node + const failable<axiom_node_t*> rnode = valuesToAxiomNode(res, ax); + if (!hasContent(rnode)) + return NULL; + return content(rnode); +} + +/** + * Return a new service skeleton. + */ +const axis2_svc_skeleton_ops_t serviceOps = { + serviceInit, + serviceInvoke, + NULL, + serviceFree, + NULL +}; + +AXIS2_EXTERN axis2_svc_skeleton_t *AXIS2_CALL serviceSkeleton(const axutil_env_t* env) { + axis2_svc_skeleton_t* svc_skeleton = (axis2_svc_skeleton_t*)AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_t)); + svc_skeleton->ops = &serviceOps; + svc_skeleton->func_array = NULL; + return svc_skeleton; +} + +} +} + +extern "C" +{ + +/** + * Axis2/C service entry point functions. + */ +AXIS2_EXPORT int axis2_get_instance(struct axis2_svc_skeleton** inst, const axutil_env_t* env) { + *inst = tuscany::webservice::serviceSkeleton(env); + if (inst == NULL) + return AXIS2_FAILURE; + return AXIS2_SUCCESS; +} + +AXIS2_EXPORT int axis2_remove_instance(axis2_svc_skeleton_t* inst, const axutil_env_t* env) { + if (inst != NULL) + return AXIS2_SVC_SKELETON_FREE(inst, env); + return AXIS2_FAILURE; +} + +} diff --git a/sca-cpp/trunk/components/webservice/axis2.hpp b/sca-cpp/trunk/components/webservice/axis2.hpp index ba13b9ad7f..7a67702b5c 100644 --- a/sca-cpp/trunk/components/webservice/axis2.hpp +++ b/sca-cpp/trunk/components/webservice/axis2.hpp @@ -25,6 +25,7 @@ /** * Web service invocation functions using Axis2. */ +#include "config.hpp" // Ignore redundant declarations in Axiom headers #ifdef WANT_MAINTAINER_MODE @@ -32,6 +33,11 @@ #endif #include <axiom.h> #include <axis2_client.h> +#include <axis2_module.h> +#include <axis2_addr_mod.h> +#include <axis2_conf_ctx.h> +#include <axis2_disp.h> +#include <axis2_http_out_transport_info.h> #ifdef WANT_MAINTAINER_MODE #pragma GCC diagnostic warning "-Wredundant-decls" #endif @@ -57,6 +63,9 @@ public: Axis2Context(const Axis2Context& ax) : env(ax.env), owner(false) { } + Axis2Context(const axutil_env_t* env) : env(const_cast<axutil_env_t*>(env)), owner(false) { + } + ~Axis2Context() { if (!owner || env == NULL) return; diff --git a/sca-cpp/trunk/components/webservice/axis2.xml b/sca-cpp/trunk/components/webservice/axis2.xml new file mode 100644 index 0000000000..ea9b6d2194 --- /dev/null +++ b/sca-cpp/trunk/components/webservice/axis2.xml @@ -0,0 +1,148 @@ +<!-- + 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. +--> +<axisconfig name="Axis2/C"> + <!-- ================================================= --> + <!-- Parameters --> + <!-- ================================================= --> + <!-- Uncomment following to enable MTOM support globally --> + <!--parameter name="enableMTOM" locked="false">true</parameter--> + + <!-- Set the suitable size for optimum memory usage when sending large attachments --> + <!--parameter name="MTOMBufferSize" locked="false">10</parameter--> + <!--parameter name="MTOMMaxBuffers" locked="false">1000</parameter--> + <!--parameter name="EnableMTOMServiceCallback" locked="false">true</parameter--> + <!--parameter name="attachmentDIR" locked="false">/path/to/the/attachment/caching/dir/</parameter--> + <!--parameter name="MTOMCachingCallback" locked="false">/path/to/the/caching_callback</parameter--> + <!--parameter name="MTOMSendingCallback" locked="false">/path/to/the/sending_callback</parameter--> + + <!-- Enable REST --> + <parameter name="enableREST" locked="false">true</parameter> + + <!-- Uncomment following to persist op_ctx, useful with RM --> + <!--parameter name="persistOperationContext" locked="false">true</parameter--> + + <!--if you want to extract the service archive file and work with that please uncomment this--> + <!--else , it wont extract archive file or does not take into consideration if someone drop--> + <!--exploded directory into /service directory--> + <!--<parameter name="extractServiceArchive" locked="false">true</parameter>--> + + + <!-- ================================================= --> + <!-- Message Receivers --> + <!-- ================================================= --> + <!-- This is the Deafult Message Receiver for the Request Response style Operations --> + <!--messageReceiver mep="INOUT" class="axis2_receivers"/--> + + + <!-- ================================================= --> + <!-- Transport Ins --> + <!-- ================================================= --> + + <transportReceiver name="http" class="axis2_http_receiver"> + <parameter name="port" locked="false">6060</parameter> + <parameter name="exposeHeaders" locked="true">false</parameter> + </transportReceiver> + + <!--transportReceiver name="https" class="axis2_http_receiver"> + <parameter name="port" locked="false">6060</parameter> + <parameter name="exposeHeaders" locked="true">false</parameter> + </transportReceiver--> + + <!--transportReceiver name="tcp" class="axis2_tcp_receiver"> + <parameter name="port" locked="false">6060</parameter> + </transportReceiver--> + + + <!-- ================================================= --> + <!-- Transport Outs --> + <!-- ================================================= --> + + <transportSender name="http" class="axis2_http_sender"> + <parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter> + <parameter name="xml-declaration" insert="false"/> + <!--parameter name="Transfer-Encoding">chunked</parameter--> + <!--parameter name="HTTP-Authentication" username="" password="" locked="true"/--> + <!--parameter name="PROXY" proxy_host="127.0.0.1" proxy_port="8080" proxy_username="" proxy_password="" locked="true"/--> + </transportSender> + + <!-- Uncomment the following with appropriate parameters to enable the SSL transport sender. + Also make sure that the appropriate transport receiver is enabled above.--> + <!--transportSender name="https" class="axis2_http_sender"> + <parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter> + <parameter name="xml-declaration" insert="false"/> + </transportSender> + <parameter name="SERVER_CERT">/path/to/ca/certificate</parameter> + <parameter name="KEY_FILE">/path/to/client/certificate/chain/file</parameter> + <parameter name="SSL_PASSPHRASE">passphrase</parameter> + --> + + <!-- Uncomment this one with the appropriate papameters to enable the TCP transport Sender--> + <!--transportSender name="tcp" class="axis2_tcp_sender"> + <parameter name="PROTOCOL" locked="false">TCP</parameter> + <parameter name="xml-declaration" insert="false"/> + </transportSender--> + + + <!-- ================================================= --> + <!-- Global Modules --> + <!-- ================================================= --> + <!-- Comment this to disable Addressing --> + <module ref="addressing"/> + + <!-- Tuscany dispatcher module --> + <module ref="tuscany"/> + + <!--Configuring module , providing paramters for modules whether they refer or not--> + <!--<moduleConfig name="addressing">--> + <!--<parameter name="addressingPara" locked="false">N/A</parameter>--> + <!--</moduleConfig>--> + + <!-- ================================================= --> + <!-- Phases --> + <!-- ================================================= --> + <phaseOrder type="inflow"> + <!-- System pre defined phases --> + <phase name="Transport"/> + <phase name="PreDispatch"/> + <phase name="Dispatch"/> + <phase name="PostDispatch"/> + <!--phase name="Security"/--> + <!-- End system pre defined phases --> + <!-- After PostDispatch phase, module or service author can add any phase as required --> + <!-- User defined phases could be added here --> + <!--phase name="userphase1"/--> + </phaseOrder> + <phaseOrder type="outflow"> + <!-- User defined phases could be added here --> + <!--phase name="userphase1"/--> + <!--system predefined phase--> + <phase name="MessageOut"/> + <!--phase name="Security"/--> + </phaseOrder> + <phaseOrder type="INfaultflow"> + <!-- User defined phases could be added here --> + <!--phase name="userphase1"/--> + </phaseOrder> + <phaseOrder type="Outfaultflow"> + <!-- User defined phases could be added here --> + <!--phase name="userphase1"/--> + <phase name="MessageOut"/> + </phaseOrder> +</axisconfig> + diff --git a/sca-cpp/trunk/components/webservice/client-test.cpp b/sca-cpp/trunk/components/webservice/client-test.cpp index 7c1cd601e0..9030a77676 100644 --- a/sca-cpp/trunk/components/webservice/client-test.cpp +++ b/sca-cpp/trunk/components/webservice/client-test.cpp @@ -32,11 +32,33 @@ #include "monad.hpp" #include "perf.hpp" #include "../../modules/http/curl.hpp" +#include "axis2.hpp" namespace tuscany { namespace webservice { +bool testModAxis2() { + const Axis2Context ax; + + const value func = "http://ws.apache.org/axis2/c/samples/echoString"; + const list<value> arg = mklist<value>( + list<value>() + "ns1:echoString" + + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (list<value>() + "text" + string("Hello World!"))); + + const failable<value> rval = evalExpr(mklist<value>(func, arg, string("http://localhost:8090/echo-listener")), ax); + assert(hasContent(rval)); + + const list<value> r = mklist<value>( + list<value>() + "ns1:echoString" + + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + + (list<value>() + "text" + string("Hello World!"))); + assert(content(rval) == r); + + return true; +} + bool testEval() { http::CURLSession cs; @@ -63,6 +85,7 @@ bool testEval() { int main() { tuscany::cout << "Testing..." << tuscany::endl; + tuscany::webservice::testModAxis2(); tuscany::webservice::testEval(); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/components/webservice/echo-test b/sca-cpp/trunk/components/webservice/echo-test index eedefed7ca..b999b1aede 100755 --- a/sca-cpp/trunk/components/webservice/echo-test +++ b/sca-cpp/trunk/components/webservice/echo-test @@ -18,7 +18,7 @@ # under the License. # Setup -axis2="${AXIS2C_HOME}/bin/axis2_http_server" +axis2="$AXIS2C_HOME/bin/axis2_http_server" pwd=`pwd` cd $AXIS2C_HOME/bin $axis2 & @@ -30,6 +30,6 @@ sleep 1 rc=$? # Cleanup -kill `ps -f | grep -v grep | grep "${axis2}" | awk '{ print $2 }'` +kill `ps -f | grep -v grep | grep "$axis2" | awk '{ print $2 }'` sleep 1 return $rc diff --git a/sca-cpp/trunk/components/webservice/module.xml b/sca-cpp/trunk/components/webservice/module.xml new file mode 100644 index 0000000000..8f6ba5018f --- /dev/null +++ b/sca-cpp/trunk/components/webservice/module.xml @@ -0,0 +1,25 @@ +<!-- + 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. +--> +<module name="tuscany" class="axis2-dispatcher"> + <inflow> + <handler name="TuscanyDispatcher" class="axis2-dispatcher"> + <order phase="Dispatch"/> + </handler> + </inflow> +</module> diff --git a/sca-cpp/trunk/components/webservice/server-test b/sca-cpp/trunk/components/webservice/server-test index 53765cca46..eb3d53a33a 100755 --- a/sca-cpp/trunk/components/webservice/server-test +++ b/sca-cpp/trunk/components/webservice/server-test @@ -21,6 +21,7 @@ ../../modules/http/httpd-conf tmp 8090 ../../modules/http/htdocs ../../modules/server/server-conf tmp ../../modules/server/scheme-conf tmp +./axis2-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> @@ -31,7 +32,7 @@ EOF apachectl -k start -d `pwd`/tmp -axis2="${AXIS2C_HOME}/bin/axis2_http_server" +axis2="$AXIS2C_HOME/bin/axis2_http_server" pwd=`pwd` cd $AXIS2C_HOME/bin $axis2 & @@ -43,7 +44,7 @@ sleep 2 rc=$? # Cleanup -kill `ps -f | grep -v grep | grep "${axis2}" | awk '{ print $2 }'` +kill `ps -f | grep -v grep | grep "$axis2" | awk '{ print $2 }'` apachectl -k stop -d `pwd`/tmp sleep 2 return $rc diff --git a/sca-cpp/trunk/components/webservice/server-test.scm b/sca-cpp/trunk/components/webservice/server-test.scm new file mode 100644 index 0000000000..22c6f71095 --- /dev/null +++ b/sca-cpp/trunk/components/webservice/server-test.scm @@ -0,0 +1,4 @@ +; Web service test case + +(define (echoString x) x) + diff --git a/sca-cpp/trunk/components/webservice/services.xml b/sca-cpp/trunk/components/webservice/services.xml new file mode 100644 index 0000000000..0adf136f4f --- /dev/null +++ b/sca-cpp/trunk/components/webservice/services.xml @@ -0,0 +1,25 @@ +<?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. +--> +<serviceGroup> +<service name="TuscanyService"> + <parameter name="ServiceClass" locked="xsd:false">axis2-service</parameter> + <operation name="execute"/> +</service> +</serviceGroup> diff --git a/sca-cpp/trunk/components/webservice/webservice-listener.cpp b/sca-cpp/trunk/components/webservice/webservice-listener.cpp index 495eb3478c..7198a00749 100644 --- a/sca-cpp/trunk/components/webservice/webservice-listener.cpp +++ b/sca-cpp/trunk/components/webservice/webservice-listener.cpp @@ -35,17 +35,40 @@ namespace tuscany { namespace webservice { /** + * Redirect an HTTP request to the Axis2/C HTTPD module. The given relay lambda function + * is stored in the HTTPD request, for later retrieval by the Axis2 service to relay the request + * to a target component. + */ +extern "C" { + extern module axis2_module; +} + +const value redirectToAxis2(const string& uri, request_rec* r, const value& relay) { + const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r); + if (!hasContent(nr)) + return value(reason(nr)); + ap_set_module_config(content(nr)->request_config, &axis2_module, const_cast<void*>((const void*)&relay)); + return value(httpd::internalRedirect(content(nr))); +} + +/** * Handle an HTTP request. */ const failable<value> handle(const list<value>& params) { - // Extract HTTPD request and relay reference - unused request_rec* r = httpd::request(car(params)); - const lambda<value(const list<value>&)> relay = cadr(params); + // Extract HTTPD request from the params + request_rec* r = httpd::request(car(params)); + httpdDebugRequest(r, "webservice::handle"); - //TODO Hook Axis2/C server module here + // Extract the relay lambda from the params and store it in the HTTPD request, + // for later retrieval by our Axis2 service + const value relay = cadr(params); + cout << "relay: " << &relay << endl; - return value(true); + // Redirect HTTPD request to Mod-axis2 + if (r->args == NULL) + return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri)), r, relay); + return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri), string(r->args)), r, relay); } } diff --git a/sca-cpp/trunk/components/webservice/webservice.composite b/sca-cpp/trunk/components/webservice/webservice.composite index bbfc926e2e..6d4055aad3 100644 --- a/sca-cpp/trunk/components/webservice/webservice.composite +++ b/sca-cpp/trunk/components/webservice/webservice.composite @@ -39,7 +39,7 @@ </component> <component name="echo"> - <t:implementation.scheme script="echo.scm"/> + <t:implementation.scheme script="server-test.scm"/> <service name="echo"> <t:binding.jsonrpc uri="echo"/> </service> diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index b1a5e8a489..4dacb6e002 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -146,7 +146,6 @@ cxxflags="${cxxflags} ${INCLUDES} -I. -I${TUSCANY_SCACPP}/kernel -I${APR_INCLUDE AC_MSG_NOTICE([checking for required libraries]) LIBS="-L${APR_LIB} ${defaultlibs}" AC_CHECK_LIB([apr-1], [apr_pool_initialize], [AC_MSG_NOTICE([found])], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])]) -AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [AC_MSG_NOTICE([found])], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])]) ldflags="${ldflags} -L${APR_LIB} -R${APR_LIB} -lapr-1 -laprutil-1" # Check for libraries only required by some modules and add their search path to LD options. diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 1e8f2a80b5..43e75bf769 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -41,6 +41,7 @@ #include "http_main.h" #include "util_script.h" #include "util_md5.h" +#include "http_config.h" #include "mod_core.h" @@ -265,17 +266,142 @@ const int reportStatus(const failable<int>& rc) { } /** - * Convert an HTTPD request struct to a value + * Construct a redirect URI. */ -const value requestValue(request_rec* r) { - return value((const value*)r); +const string redirectURI(const string& file, const string& pi) { + return file + pi; +} + +const string redirectURI(const string& file, const string& pi, const string& args) { + return file + pi + "?" + args; } /** * Convert a value to an HTTPD request struc */ request_rec* request(const value& v) { - return (request_rec*)(const value*)gc_ptr<value>(v); + return (request_rec*)(long)(double)v; +} + +/** + * Convert an HTTPD request struct to a value + */ +const value requestValue(request_rec* r) { + return value((double)(long)r); +} + +/** + * Update filters in an HTTPD redirect request. + * Similar to httpd/modules/http/http_request.c::update_r_in_filters. + */ +const bool redirectFilters(ap_filter_t* f, request_rec* from, request_rec* to) { + if (f == NULL) + return true; + if (f->r == from) + f->r = to; + return redirectFilters(f->next, from, to); +} + +/** + * Create an HTTPD redirect request. + * Similar to httpd/modules/http/http_request.c::internal_internal_redirect. + */ +extern "C" { + AP_DECLARE(ap_conf_vector_t*) ap_create_request_config(apr_pool_t *p); +} + +const failable<request_rec*, int> internalRedirectRequest(const string& nr_uri, request_rec* r) { + if (ap_is_recursion_limit_exceeded(r)) + return mkfailure<request_rec*, int>(HTTP_INTERNAL_SERVER_ERROR); + + // Create a new request + request_rec* nr = (request_rec*)apr_pcalloc(r->pool, sizeof(request_rec)); + nr->connection = r->connection; + nr->server = r->server; + nr->pool = r->pool; + nr->method = r->method; + nr->method_number = r->method_number; + nr->allowed_methods = ap_make_method_list(nr->pool, 2); + ap_parse_uri(nr, apr_pstrdup(nr->pool, c_str(nr_uri))); + nr->request_config = ap_create_request_config(r->pool); + nr->per_dir_config = r->server->lookup_defaults; + nr->prev = r; + r->next = nr; + + // Run create request hook + ap_run_create_request(nr); + + // Inherit protocol info from the original request + nr->the_request = r->the_request; + nr->allowed = r->allowed; + nr->status = r->status; + nr->assbackwards = r->assbackwards; + nr->header_only = r->header_only; + nr->protocol = r->protocol; + nr->proto_num = r->proto_num; + nr->hostname = r->hostname; + nr->request_time = r->request_time; + nr->main = r->main; + nr->headers_in = r->headers_in; + nr->headers_out = apr_table_make(r->pool, 12); + nr->err_headers_out = r->err_headers_out; + nr->subprocess_env = r->subprocess_env; + nr->notes = apr_table_make(r->pool, 5); + nr->allowed_methods = ap_make_method_list(nr->pool, 2); + nr->htaccess = r->htaccess; + nr->no_cache = r->no_cache; + nr->expecting_100 = r->expecting_100; + nr->no_local_copy = r->no_local_copy; + nr->read_length = r->read_length; + nr->vlist_validator = r->vlist_validator; + + // Setup input and output filters + nr->proto_output_filters = r->proto_output_filters; + nr->proto_input_filters = r->proto_input_filters; + nr->output_filters = nr->proto_output_filters; + nr->input_filters = nr->proto_input_filters; + if (nr->main) + ap_add_output_filter_handle(ap_subreq_core_filter_handle, NULL, nr, nr->connection); + redirectFilters(nr->input_filters, r, nr); + redirectFilters(nr->output_filters, r, nr); + const int rrc = ap_run_post_read_request(nr); + if (rrc != OK && rrc != DECLINED) + return mkfailure<request_rec*, int>(rrc); + + return nr; +} + +/** + * Process an HTTPD internal redirect request. + * Similar to httpd/modules/http/http_request.c::ap_internal_redirect. + */ +extern "C" { + AP_DECLARE(int) ap_invoke_handler(request_rec *r); +} + +const int internalRedirect(request_rec* nr) { + int status = ap_run_quick_handler(nr, 0); + if (status == DECLINED) { + status = ap_process_request_internal(nr); + if (status == OK) + status = ap_invoke_handler(nr); + } + if (status != OK) { + nr->status = status; + return OK; + } + ap_finalize_request_protocol(nr); + return OK; +} + +/** + * Create and process an HTTPD redirect request. + */ +const int internalRedirect(const string& uri, request_rec* r) { + const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r); + if (!hasContent(nr)) + return reason(nr); + return httpd::internalRedirect(content(nr)); } } diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index 41ac24a22e..b74f068710 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -78,7 +78,6 @@ bool testJSON() { } { const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!"))); - cout << "l: " << l << endl; ostringstream wos; write(content(writeJSON(valuesToElements(l), cx)), wos); assert(str(wos) == "{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\"text\":\"Hello World!\"}}"); diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index aaf31f2b18..b622283fed 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -129,13 +129,18 @@ 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 list<string> ls = httpd::read(r); debug(r->uri, "modeval::post::url"); - debug(ls, "modeval::post::input"); // Evaluate a JSON-RPC request and return a JSON result const string ct = httpd::contentType(r); if (contains(ct, "application/json-rpc") || contains(ct, "text/plain")) { + + // Read the JSON request + const int rc = httpd::setupReadPolicy(r); + if(rc != OK) + return rc; + const list<string> ls = httpd::read(r); + debug(ls, "modeval::post::input"); json::JSONContext cx; const list<value> json = elementsToValues(content(json::readJSON(ls, cx))); const list<list<value> > args = httpd::postArgs(json); @@ -157,8 +162,15 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> // Evaluate an ATOM POST request and return the location of the corresponding created resource if (contains(ct, "application/atom+xml")) { - // Evaluate the request expression + // Read the ATOM entry + const int rc = httpd::setupReadPolicy(r); + if(rc != OK) + return rc; + const list<string> ls = httpd::read(r); + debug(ls, "modeval::post::input"); const value entry = atom::entryValue(content(atom::readEntry(ls))); + + // Evaluate the request expression const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(entry)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -174,20 +186,25 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)> const failable<value> val = failableResult(impl(cons<value>("handle", mklist<value>(httpd::requestValue(r))))); if (!hasContent(val)) return mkfailure<int>(reason(val)); - return OK; + return (int)content(val); } /** * Handle an HTTP PUT. */ const failable<int> put(request_rec* r, const lambda<value(const list<value>&)>& impl) { - const list<string> ls = httpd::read(r); debug(r->uri, "modeval::put::url"); - debug(ls, "modeval::put::input"); - // Evaluate an ATOM PUT request and update the corresponding resource + // Read the ATOM entry const list<value> path(httpd::pathValues(r->uri)); + const int rc = httpd::setupReadPolicy(r); + if(rc != OK) + return rc; + const list<string> ls = httpd::read(r); + debug(ls, "modeval::put::input"); const value entry = atom::entryValue(content(atom::readEntry(ls))); + + // Evaluate the ATOM PUT request and update the corresponding resource const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -244,11 +261,6 @@ int handler(request_rec *r) { return DECLINED; httpdDebugRequest(r, "modeval::handler::input"); - // Set up the read policy - const int rc = httpd::setupReadPolicy(r); - if(rc != OK) - return rc; - // Get the component implementation lambda DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_eval); const list<value> path(httpd::pathValues(r->uri)); diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index 88a57659ef..aef2f00c83 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -194,17 +194,6 @@ int translate(request_rec *r) { } /** - * Construct a redirect URI. - */ -const string redirect(const string& file, const string& pi) { - return file + pi; -} - -const string redirect(const string& file, const string& pi, const string& args) { - return file + pi + "?" + args; -} - -/** * HTTP request handler, redirect to a target component. */ int handler(request_rec *r) { @@ -220,12 +209,9 @@ int handler(request_rec *r) { debug(r->filename, "modwiring::handler::filename"); debug(r->path_info, "modwiring::handler::path info"); - if (r->args == NULL) { - ap_internal_redirect(apr_pstrdup(r->pool, c_str(redirect(string(r->filename + 10), string(r->path_info)))), r); - return OK; - } - ap_internal_redirect(apr_pstrdup(r->pool, c_str(redirect(string(r->filename + 10), string(r->path_info), string(r->args)))), r); - return OK; + 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); } /** |