diff options
Diffstat (limited to 'sca-cpp/trunk')
57 files changed, 1341 insertions, 935 deletions
diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL index 0e82c54f0b..33aa589cfe 100644 --- a/sca-cpp/trunk/INSTALL +++ b/sca-cpp/trunk/INSTALL @@ -56,6 +56,15 @@ To enable gprof profiling, add: To enable multi-threading with the HTTPD worker MPM, add: --enable-threads +To enable support for Python component implementations: +--enable-python + +To enable support for Java component implementations: +--enable-java + +To build the Web service utility component (using Axis2C): +--enable-webservice + To generate doxygen documentation, add: --enable-doxygen @@ -70,10 +79,12 @@ HTTPD worker MPM in $HOME/httpd-2-2.13-bin: ./configure --prefix=$HOME/tuscany-sca-cpp-bin \ --with-apr=$HOME/httpd-2.2.13-bin --with-httpd=$HOME/httpd-2.2.13-bin \ +--with-curl=/usr --with-libxml2=/usr \ --with-js-include=/usr/include/xulrunner-1.9.1.5/unstable \ --with-js-lib=/usr/lib/xulrunner-1.9.1.5 \ ---with-python=/usr \ ---with-curl=/usr --with-libxml2=/usr \ +--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 @@ -99,4 +110,3 @@ Installing To install the Tuscany SCA binaries, do this: make install - diff --git a/sca-cpp/trunk/components/Makefile.am b/sca-cpp/trunk/components/Makefile.am index 1d57e707c5..0f1cd48197 100644 --- a/sca-cpp/trunk/components/Makefile.am +++ b/sca-cpp/trunk/components/Makefile.am @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = cache store +SUBDIRS = cache store webservice includedir = $(prefix)/include/components nobase_include_HEADERS = */*.hpp diff --git a/sca-cpp/trunk/components/cache/Makefile.am b/sca-cpp/trunk/components/cache/Makefile.am index 22410eb611..fa6c61607d 100644 --- a/sca-cpp/trunk/components/cache/Makefile.am +++ b/sca-cpp/trunk/components/cache/Makefile.am @@ -15,20 +15,17 @@ # specific language governing permissions and limitations # under the License. -noinst_PROGRAMS = mcache-test mcache-client-test - -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${JS_INCLUDE} -I${CURL_INCLUDE} +noinst_PROGRAMS = mcache-test client-test compdir=$(prefix)/components/cache comp_LTLIBRARIES = libmcache.la libmcache_la_SOURCES = mcache.cpp -libmcache_la_LIBADD = -L${APR_LIB} -lapr-1 -laprutil-1 mcache_test_SOURCES = mcache-test.cpp -mcache_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +mcache_test_LDADD = -lxml2 -mcache_client_test_SOURCES = mcache-client-test.cpp -mcache_client_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${JS_LIB} -lmozjs +client_test_SOURCES = client-test.cpp +client_test_LDADD = -lxml2 -lcurl -lmozjs -TESTS = memcached-test memcached-server-test +TESTS = memcached-test server-test diff --git a/sca-cpp/trunk/components/cache/mcache.hpp b/sca-cpp/trunk/components/cache/mcache.hpp index fac9c7dbb3..9659c11788 100644 --- a/sca-cpp/trunk/components/cache/mcache.hpp +++ b/sca-cpp/trunk/components/cache/mcache.hpp @@ -38,7 +38,6 @@ #include "list.hpp" #include "value.hpp" #include "monad.hpp" -#include "debug.hpp" #include "../../modules/scheme/eval.hpp" namespace tuscany { diff --git a/sca-cpp/trunk/components/cache/server-test b/sca-cpp/trunk/components/cache/server-test index 68c59a62e7..a30d14b1b6 100755 --- a/sca-cpp/trunk/components/cache/server-test +++ b/sca-cpp/trunk/components/cache/server-test @@ -20,6 +20,7 @@ # Setup ../../modules/http/httpd-conf tmp 8090 ../../modules/http/htdocs ../../modules/server/server-conf tmp +../../modules/server/scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index f5da38d537..9b284fe8f1 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -25,7 +25,7 @@ AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE([tar-ustar]) AC_PREFIX_DEFAULT(/usr/local/tuscany/sca) -# Checks for programs. +# Check for required programs. AC_MSG_NOTICE([checking for programs]) AC_PROG_CXX AC_PROG_AWK @@ -35,23 +35,26 @@ AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_LIBTOOL +AC_PATH_PROG(MEMCACHED, memcached, , ${PATH}) +if test "${MEMCACHED}" = ""; then + AC_MSG_ERROR([could not find memcached]) +fi -# Check for running on Darwin +# Check for running on Darwin. AC_MSG_CHECKING([if running on Darwin]) UNAME=`uname -s` if test "${UNAME}" = "Darwin"; then - AC_DEFINE([IS_DARWIN], [1], [Set to 1 when running on Darwin - Mac OSX]) + AC_DEFINE([IS_DARWIN], 1, [running on Darwin]) AC_MSG_RESULT(yes) AC_SUBST([libsuffix],[".dylib"]) - is_darwin=true + AM_CONDITIONAL([DARWIN], true) else AC_MSG_RESULT(no) AC_SUBST([libsuffix],[".so"]) - is_darwin=false + AM_CONDITIONAL([DARWIN], false) fi -AM_CONDITIONAL([DARWIN], [test "${is_darmin}" = "true"]) -# Configure CURL_INCLUDE and CURL_LIB +# Configure path to CURL includes and lib. AC_MSG_CHECKING([for curl]) AC_ARG_WITH([curl], [AC_HELP_STRING([--with-curl=PATH], [path to installed curl [default=/usr]])], [ CURL_INCLUDE="${withval}/include" @@ -65,7 +68,7 @@ AC_ARG_WITH([curl], [AC_HELP_STRING([--with-curl=PATH], [path to installed curl AC_SUBST(CURL_INCLUDE) AC_SUBST(CURL_LIB) -# Configure LIBXML2_INCLUDE and LIBXML2_LIB +# Configure path to libxml2 includes and lib. AC_MSG_CHECKING([for libxml2]) AC_ARG_WITH([libxml2], [AC_HELP_STRING([--with-libxml2=PATH], [path to installed libxml2 [default=/usr]])], [ LIBXML2_INCLUDE="${withval}/include/libxml2" @@ -79,7 +82,7 @@ AC_ARG_WITH([libxml2], [AC_HELP_STRING([--with-libxml2=PATH], [path to installed AC_SUBST(LIBXML2_INCLUDE) AC_SUBST(LIBXML2_LIB) -# Configure LIBMOZJS_INCLUDE and LIBMOZJS_LIB +# Configure path to libmozjs includes and lib. AC_MSG_CHECKING([for js-include]) AC_ARG_WITH([js-include], [AC_HELP_STRING([--with-js-include=PATH], [path to installed SpiderMonkey include dir [default=/usr/include/xulrunner-1.9.1.5/unstable]])], [ @@ -100,9 +103,9 @@ AC_ARG_WITH([js-lib], [AC_HELP_STRING([--with-js-lib=PATH], [path to installed S AC_SUBST(JS_INCLUDE) AC_SUBST(JS_LIB) -# Configure APR and HTTPD +# Configure path to APR and HTTPD includes and libs. AC_MSG_CHECKING([for apr]) -AC_ARG_WITH([apr], [AC_HELP_STRING([--with-apr=PATH], [path to installed apr [default=/usr/local/apache2]])], [ +AC_ARG_WITH([apr], [AC_HELP_STRING([--with-apr=PATH], [path to installed APR [default=/usr/local/apache2]])], [ APR_INCLUDE="${withval}/include" APR_LIB="${withval}/lib" AC_MSG_RESULT("${withval}") @@ -115,7 +118,7 @@ AC_SUBST(APR_INCLUDE) AC_SUBST(APR_LIB) AC_MSG_CHECKING([for httpd]) -AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed httpd [default=/usr/local/apache2]])], [ +AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed HTTPD [default=/usr/local/apache2]])], [ HTTPD_INCLUDE="${withval}/include" AC_MSG_RESULT("${withval}") ], [ @@ -124,60 +127,57 @@ AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed htt ]) AC_SUBST(HTTPD_INCLUDE) -# Configure PYTHON_INCLUDE and PYTHON_LIB -AC_MSG_CHECKING([for python]) -AC_ARG_WITH([curl], [AC_HELP_STRING([--with-python=PATH], [path to installed python 2.6 [default=/usr]])], [ - PYTHON_INCLUDE="${withval}/include" - PYTHON_LIB="${withval}/lib" - AC_MSG_RESULT("${withval}") -], [ - PYTHON_INCLUDE="/usr/include" - PYTHON_LIB="/usr/lib" - AC_MSG_RESULT(/usr) -]) -AC_SUBST(PYTHON_INCLUDE) -AC_SUBST(PYTHON_LIB) +# Configure TUSCANY_SCACPP path variable. +TUSCANY_SCACPP=`echo "${TUSCANY_SCACPP}"` +if test "${TUSCANY_SCACPP}" = ""; then + pwd=`pwd` + AC_SUBST([TUSCANY_SCACPP], ["${pwd}"]) +fi -# Checks for libraries. -original_LIBS="${LIBS}" -AC_MSG_NOTICE([checking for libraries]) -LIBS="-L${CURL_LIB} ${original_LIBS}" +# Initialize default GCC C++ and LD options. +cxxflags="" +ldflags="${LDFLAGS}" + +# Configure default includes. +cxxflags="${cxxflags} ${INCLUDES} -I. -I${TUSCANY_SCACPP}/kernel -I${APR_INCLUDE} -I${LIBXML2_INCLUDE} -I${JS_INCLUDE} -I${CURL_INCLUDE}" + +# Check for libraries required by all modules and add them to default LIBS variable +AC_MSG_NOTICE([checking for required libraries]) +LIBS="-L${APR_LIB} ${LIBS}" +AC_CHECK_LIB([apr-1], [apr_pool_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])]) +AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])]) +default_LIBS="${LIBS}" + +# Check for libraries only required by some modules. +LIBS="-L${CURL_LIB} ${default_LIBS}" AC_CHECK_LIB([curl], [curl_global_init], [], [AC_MSG_ERROR([couldn't find a suitable libcurl, use --with-curl=PATH])]) -LIBS="-L${JS_LIB} ${original_LIBS}" +LIBS="-L${JS_LIB} ${default_LIBS}" AC_CHECK_LIB([mozjs], [JS_NewContext], [], [AC_MSG_ERROR([couldn't find a suitable libmozjs, use --with-js-lib=PATH])]) -LIBS="${original_LIBS}" -AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([couldn't find a suitable libpthread])]) -LIBS="-L${LIBXML2_LIB} ${original_LIBS}" +LIBS="-L${LIBXML2_LIB} ${default_LIBS}" AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitable libxml2, use --with-libxml2=PATH])]) -LIBS="-L${APR_LIB} ${original_LIBS}" -AC_CHECK_LIB([apr-1], [apr_pool_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])]) -AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])]) -LIBS="-L${PYTHON_LIB} ${original_LIBS}" -AC_CHECK_LIB([python2.6], [Py_Initialize], [], [AC_MSG_ERROR([couldn't find a suitable libpython2.6, use --with-python=PATH])]) -LIBS="${original_LIBS}" -# Checks for header files. +# Configure default search path for these libraries. +LIBS="-L${CURL_LIB} -L${JS_LIB} -L${LIBXML2_LIB} ${default_LIBS}" +default_LIBS="${LIBS}" + +# Check for required header files. AC_MSG_NOTICE([checking for header files]) AC_HEADER_DIRENT AC_HEADER_STDC AC_CHECK_HEADERS([string.h sys/time.h]) -# Checks for typedefs, structures, and compiler characteristics. +# Check for typedefs, structures, and compiler characteristics. AC_MSG_NOTICE([checking for typedefs, structures, and compiler characteristics]) AC_HEADER_STDBOOL AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T -# Checks for library functions. +# Check for required library functions. AC_MSG_NOTICE([checking for library functions]) AC_CHECK_FUNCS([gettimeofday select]) -# Configure GCC C++ compile options -cxxflags="" -ldflags="${LDFLAGS}" - -# Configure debugging and compile-time warnings +# Enable debugging and compile-time warnings. AC_MSG_CHECKING([whether to compile with debugging and compile-time warnings]) AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [compile with debugging and compile-time warnings [default=no]])], [ case "${enableval}" in @@ -193,11 +193,14 @@ AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [comp if test "${want_maintainer_mode}" = "true"; then cxxflags="${cxxflags} -D_DEBUG -O0 -ggdb -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0" ldflags="${ldflags} -pg" + AM_CONDITIONAL([WANT_MAINTAINER_MODE], true) + AC_DEFINE([WANT_MAINTAINER_MODE], 1, [compile with debugging and compile-time warnings]) else cxxflags="${cxxflags} -O3 -std=c++0x -fmessage-length=0" + AM_CONDITIONAL([WANT_MAINTAINER_MODE], false) fi -# Configure profiling +# Enable profiling with gprof. AC_MSG_CHECKING([whether to compile with profiling]) AC_ARG_ENABLE(profiling, [AS_HELP_STRING([--enable-profiling], [compile with profiling [default=no]])], [ case "${enableval}" in @@ -213,9 +216,13 @@ AC_ARG_ENABLE(profiling, [AS_HELP_STRING([--enable-profiling], [compile with pro if test "${want_profiling}" = "true"; then cxxflags="${cxxflags} -pg" ldflags="${ldflags} -pg" + AM_CONDITIONAL([WANT_PROFILING], true) + AC_DEFINE([WANT_PROFILING], 1, [compile with profiling]) +else + AM_CONDITIONAL([WANT_PROFILING], false) fi -# Configure multi-threading support +# Enable multi-threading support. AC_MSG_CHECKING([whether to compile for multi-threaded execution]) AC_ARG_ENABLE(threads, [AS_HELP_STRING([--enable-threads], [compile for multi-threaded execution [default=no]])], [ case "${enableval}" in @@ -229,27 +236,26 @@ AC_ARG_ENABLE(threads, [AS_HELP_STRING([--enable-threads], [compile for multi-th esac ], [ AC_MSG_RESULT(no)]) if test "${want_threads}" = "true"; then - LIBS="${original_LIBS}" + LIBS="${default_LIBS}" AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([couldn't find a suitable libpthread])]) - LIBS="${original_LIBS}" + LIBS="${default_LIBS}" cxxflags="${cxxflags} -D_REENTRANT" ldflags="${ldflags} -lpthread" + AM_CONDITIONAL([WANT_THREADS], true) + AC_DEFINE([WANT_THREADS], 1, [compile for multi-threaded execution]) +else + AM_CONDITIONAL([WANT_THREADS], false) fi + +# Configure GCC C++ and LD options. AC_SUBST([CXXFLAGS], ["${cxxflags}"]) AC_SUBST([LDFLAGS], ["${ldflags}"]) -# Configure exuberant ctags +# Configure exuberant ctags. TAGSFILE="`pwd`/tags" AC_SUBST([CTAGSFLAGS], ["${CTAGSFLAGS} --c++-kinds=+p --fields=+iaS --extra=+q --append --tag-relative=yes -f ${TAGSFILE}"]) -# Configure TUSCANY_SCACPP -TUSCANY_SCACPP=`echo "${TUSCANY_SCACPP}"` -if test "${TUSCANY_SCACPP}" = ""; then - SCAPWD=`pwd` - AC_SUBST([TUSCANY_SCACPP], ["${SCAPWD}"]) -fi - -# Configure Doxygen build +# Enable Doxygen documentation. AC_MSG_CHECKING([whether to build Doxygen documentation]) AC_ARG_ENABLE(doxygen, [AS_HELP_STRING([--enable-doxygen], [build Doxygen documentation [default=no]])], [ case "${enableval}" in @@ -258,29 +264,149 @@ AC_ARG_ENABLE(doxygen, [AS_HELP_STRING([--enable-doxygen], [build Doxygen docume ;; *) AC_MSG_RESULT(yes) + want_doxygen=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_doxygen}" = "true"; then AC_PATH_PROG(DOXYGEN, doxygen, , ${PATH}) if test "${DOXYGEN}" = ""; then AC_MSG_ERROR([could not find doxygen]) fi - want_doxygen=true + AM_CONDITIONAL([WANT_DOXYGEN], true) + AC_DEFINE([WANT_DOXYGEN], 1, [build Doxygen documentation]) +else + AM_CONDITIONAL([WANT_DOXYGEN], false) +fi + +# Configure path to Python 2.6 includes and lib. +AC_MSG_CHECKING([for python]) +AC_ARG_WITH([python], [AC_HELP_STRING([--with-python=PATH], [path to installed Python 2.6 [default=/usr]])], [ + PYTHON_INCLUDE="${withval}/include" + PYTHON_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") +], [ + PYTHON_INCLUDE="/usr/include" + PYTHON_LIB="/usr/lib" + AC_MSG_RESULT(/usr) +]) +AC_SUBST(PYTHON_INCLUDE) +AC_SUBST(PYTHON_LIB) + +# Enable Python 2.6 support. +AC_MSG_CHECKING([whether to enable Python support]) +AC_ARG_ENABLE(python, [AS_HELP_STRING([--enable-python], [enable Python support [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_python=true ;; esac ], [ AC_MSG_RESULT(no)]) -AM_CONDITIONAL([WANT_DOXYGEN], [test "${want_doxygen}" = "true"]) +if test "${want_python}" = "true"; then + LIBS="-L${PYTHON_LIB} ${default_LIBS}" + AC_CHECK_LIB([python2.6], [Py_Initialize], [], [AC_MSG_ERROR([couldn't find a suitable libpython2.6, use --with-python=PATH])]) + LIBS="${default_LIBS}" + AM_CONDITIONAL([WANT_PYTHON], true) + AC_DEFINE([WANT_PYTHON], 1, [enable Python support]) +else + AM_CONDITIONAL([WANT_PYTHON], false) +fi + +# Configure path to Java includes and lib. +AC_MSG_CHECKING([for java]) +AC_ARG_WITH([java], [AC_HELP_STRING([--with-java=PATH], [path to installed Java [default=/usr/lib/jvm/default-java]])], [ + JAVA_INCLUDE="${withval}/include" + JAVA_LIB="${withval}/jre/lib/i386" + AC_MSG_RESULT("${withval}") +], [ + JAVA_INCLUDE="/usr/lib/jvm/default-java/include" + JAVA_LIB="/usr/lib/jvm/default-java/jre/lib/i386" + AC_MSG_RESULT(/usr/lib/jvm/default-java) +]) +AC_SUBST(JAVA_INCLUDE) +AC_SUBST(JAVA_LIB) + +# Enable Java support. +AC_MSG_CHECKING([whether to enable Java support]) +AC_ARG_ENABLE(java, [AS_HELP_STRING([--enable-java], [enable Java support [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_java=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_java}" = "true"; then + LIBS="-L${JAVA_LIB} ${default_LIBS}" + #AC_CHECK_LIB([java], [JNI_OnLoad], [], [AC_MSG_ERROR([couldn't find a suitable libjava, use --with-java=PATH])]) + LIBS="${default_LIBS}" + AC_PROG_JAVAC + AC_PROG_JAR + AM_CONDITIONAL([WANT_JAVA], true) + AC_DEFINE([WANT_JAVA], 1, [enable Java support]) +else + AM_CONDITIONAL([WANT_JAVA], false) +fi + +# Configure path to Axis2C includes and lib. +AC_MSG_CHECKING([for axis2c]) +AC_ARG_WITH([axis2c], [AC_HELP_STRING([--with-axis2c=PATH], [path to installed Axis2C [default=/usr/local/axis2c]])], [ + AXIS2C_INCLUDE="${withval}/include" + AXIS2C_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") +], [ + AXIS2C_INCLUDE="/usr/local/axis2c/include" + AXIS2C_LIB="/usr/local/axis2c/lib" + AC_MSG_RESULT(/usr/local/axis2c) +]) +AC_SUBST(AXIS2C_INCLUDE) +AC_SUBST(AXIS2C_LIB) + +# Enable Web service support. +AC_MSG_CHECKING([whether to enable Web service support]) +AC_ARG_ENABLE(webservice, [AS_HELP_STRING([--enable-webservice], [enable Web service support [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_webservice=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_webservice}" = "true"; then + LIBS="-L${AXIS2C_LIB} ${default_LIBS}" + AC_CHECK_LIB([axis2_engine], [axis2_svc_client_create], [], [AC_MSG_ERROR([couldn't find a suitable libaxis2_engine, use --with-axis2c=PATH])]) + LIBS="${default_LIBS}" + AM_CONDITIONAL([WANT_WEBSERVICE], true) + AC_DEFINE([WANT_WEBSERVICE], 1, [enable Web service support]) +else + AM_CONDITIONAL([WANT_WEBSERVICE], false) +fi AC_CONFIG_FILES([Makefile kernel/Makefile modules/Makefile - modules/atom/Makefile modules/scheme/Makefile - modules/http/Makefile + modules/atom/Makefile modules/json/Makefile - modules/python/Makefile modules/scdl/Makefile + modules/http/Makefile + modules/python/Makefile + modules/java/Makefile modules/server/Makefile components/Makefile components/cache/Makefile components/store/Makefile + components/webservice/Makefile samples/Makefile test/Makefile test/store-scheme/Makefile @@ -289,4 +415,3 @@ AC_CONFIG_FILES([Makefile doc/Doxyfile ]) AC_OUTPUT - diff --git a/sca-cpp/trunk/etc/git-exclude b/sca-cpp/trunk/etc/git-exclude index aa44227d1b..c08230fe5a 100644 --- a/sca-cpp/trunk/etc/git-exclude +++ b/sca-cpp/trunk/etc/git-exclude @@ -58,6 +58,9 @@ gmon.out *~ tags doxygen +*.pyc +*.class +*.stamp # Specific ignores kernel-test @@ -72,8 +75,10 @@ json-test cache-test client-test mcache-test -mcache-client-test curl-test scdl-test +java-test +java-shell script-test +webservice-test diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am index 507454439a..e210e0d323 100644 --- a/sca-cpp/trunk/kernel/Makefile.am +++ b/sca-cpp/trunk/kernel/Makefile.am @@ -23,27 +23,20 @@ test_LTLIBRARIES = libdynlib-test.la includedir = $(prefix)/include/kernel include_HEADERS = *.hpp -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} - string_test_SOURCES = string-test.cpp -string_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 libdynlib_test_la_SOURCES = dynlib-test.cpp -libdynlib_test_la_LIBADD = -L${APR_LIB} -lapr-1 -laprutil-1 kernel_test_SOURCES = kernel-test.cpp -kernel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 mem_test_SOURCES = mem-test.cpp -mem_test_LDADD = -L${APR_LIB} -lapr-1 -laprutil-1 parallel_test_SOURCES = parallel-test.cpp -parallel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 xml_test_SOURCES = xml-test.cpp -xml_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +xml_test_LDADD = -lxml2 xsd_test_SOURCES = xsd-test.cpp -xsd_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +xsd_test_LDADD = -lxml2 TESTS = string-test kernel-test mem-test parallel-test xml-test diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/config.hpp index f9baf73c3c..195612428e 100644 --- a/sca-cpp/trunk/kernel/debug.hpp +++ b/sca-cpp/trunk/kernel/config.hpp @@ -19,22 +19,31 @@ /* $Rev$ $Date$ */ -#ifndef tuscany_debug_hpp -#define tuscany_debug_hpp +#ifndef tuscany_config_hpp +#define tuscany_config_hpp + +#include "ap_config.h" +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + +#include "../config.h" /** - * Debug functions and macros. + * Platform configuration and debug functions. */ namespace tuscany { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Add string watch members to important classes to help watch them in a debugger. */ -#define _DEBUG_WATCH +#define WANT_MAINTAINER_WATCH /** * Increment / decrement a debug counter. @@ -64,4 +73,4 @@ bool debug_dec(long int& c) { #endif } -#endif /* tuscany_debug_hpp */ +#endif /* tuscany_config_hpp */ diff --git a/sca-cpp/trunk/kernel/dynlib-test.cpp b/sca-cpp/trunk/kernel/dynlib-test.cpp index 9d0e6a2186..419fa29db5 100644 --- a/sca-cpp/trunk/kernel/dynlib-test.cpp +++ b/sca-cpp/trunk/kernel/dynlib-test.cpp @@ -24,7 +24,6 @@ */ #include "function.hpp" -#include "debug.hpp" namespace tuscany { namespace test { diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp index b158e66084..81f6a39f64 100644 --- a/sca-cpp/trunk/kernel/fstream.hpp +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -139,7 +139,7 @@ ifstream cin(stdin); /** * Debug log stream. */ -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE template<typename V> const bool debug(const V& v, const string& msg) { cerr << msg << ": " << v << endl; diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp index 899443462e..db7318303a 100644 --- a/sca-cpp/trunk/kernel/function.hpp +++ b/sca-cpp/trunk/kernel/function.hpp @@ -29,11 +29,11 @@ #include <utility> #include "fstream.hpp" #include "gc.hpp" -#include "debug.hpp" +#include "config.hpp" namespace tuscany { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug counters. diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index bfb304615d..4b29d66d64 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -31,7 +31,7 @@ #include <apr_pools.h> #include <assert.h> #include <new> -#include "debug.hpp" +#include "config.hpp" namespace tuscany { @@ -139,7 +139,7 @@ public: /** * Maintain a stack of memory pools. */ -#ifdef _REENTRANT +#ifdef WANT_THREADS __thread #endif apr_pool_t* gc_pool_stack = NULL; diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index 6a725d0382..84eba6d82f 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -30,11 +30,10 @@ #include "string.hpp" #include "fstream.hpp" #include "function.hpp" -#include "debug.hpp" namespace tuscany { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug utilities. Counters used to track instances of lists, and @@ -71,7 +70,7 @@ bool printListCounters() { #endif -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH #define debug_watchList() do { \ this->watch = watchList(*this); \ @@ -105,7 +104,7 @@ public: list(const list& p) : car(p.car), cdr(p.cdr) { debug_inc(countLists); debug_inc(countCLists); -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH watch = p.watch; #endif } @@ -115,7 +114,7 @@ public: return *this; car = p.car; cdr = p.cdr; -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH watch = p.watch; #endif return *this; @@ -176,7 +175,7 @@ public: } private: -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH template<typename X> friend const string watchList(const list<X>& p); string watch; #endif @@ -189,7 +188,7 @@ private: lambda<list<T>()> cdr; }; -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH /** * Debug utility used to write the contents of a list to a string, easier diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp index 15029b20ec..a312827f6e 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -27,7 +27,6 @@ */ #include "function.hpp" -#include "debug.hpp" #include "string.hpp" #include "stream.hpp" diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp index b47501a58d..2969dd0637 100644 --- a/sca-cpp/trunk/kernel/parallel-test.cpp +++ b/sca-cpp/trunk/kernel/parallel-test.cpp @@ -33,7 +33,7 @@ namespace tuscany { -#ifdef _REENTRANT +#ifdef WANT_THREADS int inci = 0; @@ -153,7 +153,7 @@ bool testWorker() { int main() { tuscany::cout << "Testing..." << tuscany::endl; -#ifdef _REENTRANT +#ifdef WANT_THREADS tuscany::testAtomicPerf(); tuscany::testWorker(); #else diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp index 30697004f2..9fb6c59ba7 100644 --- a/sca-cpp/trunk/kernel/parallel.hpp +++ b/sca-cpp/trunk/kernel/parallel.hpp @@ -26,7 +26,7 @@ * Simple parallel work execution functions. */ -#ifdef _REENTRANT +#ifdef WANT_THREADS #include <pthread.h> #include <sys/syscall.h> #include <unistd.h> @@ -37,7 +37,7 @@ namespace tuscany { -#ifdef _REENTRANT +#ifdef WANT_THREADS /** * Returns the current thread id. diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp index f3efb13479..32b754f315 100644 --- a/sca-cpp/trunk/kernel/stream.hpp +++ b/sca-cpp/trunk/kernel/stream.hpp @@ -27,7 +27,7 @@ */ #include <stdarg.h> -#include "debug.hpp" +#include "config.hpp" #include "gc.hpp" #include "string.hpp" @@ -152,7 +152,7 @@ template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { return out << p.ptr; } -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug stream implementation with no dependencies on anything else. diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp index 9a3af49fc7..931417e430 100644 --- a/sca-cpp/trunk/kernel/string.hpp +++ b/sca-cpp/trunk/kernel/string.hpp @@ -34,7 +34,7 @@ namespace tuscany { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug utilities. Counters used to track string copies. @@ -67,7 +67,7 @@ bool printStringCopyCounters() { * Instrumented memcpy. */ void* string_memcpy(void* t, const void* s, const size_t n) { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE countStringCopies += 1; #endif return memcpy(t, s, n); @@ -172,7 +172,7 @@ public: } private: -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE friend class odebugstream; #endif friend class ostringstream; diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index a6c3fbd3f7..4f19ee3915 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -33,12 +33,11 @@ #include "function.hpp" #include "list.hpp" #include "monad.hpp" -#include "debug.hpp" namespace tuscany { -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug utilities. Counters used to track instances of values, and @@ -75,7 +74,7 @@ bool printValueCounters() { #endif -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH #define debug_watchValue() do { \ this->watch = watchValue(*this); \ @@ -124,7 +123,7 @@ public: default: break; } -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH watch = v.watch; #endif } @@ -223,7 +222,7 @@ public: default: break; } -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH watch = v.watch; #endif return *this; @@ -420,7 +419,7 @@ private: friend ostream& operator<<(ostream&, const value&); friend const value::ValueType type(const value& v); -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH friend const string watchValue(const value& v); string watch; #endif @@ -429,7 +428,7 @@ private: lambda<char()> data; }; -#ifdef _DEBUG_WATCH +#ifdef WANT_MAINTAINER_WATCH /** * Debug utility used to write the contents of a value to a string, easier diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am index 85ac1c88fd..4332bbe7c8 100644 --- a/sca-cpp/trunk/modules/Makefile.am +++ b/sca-cpp/trunk/modules/Makefile.am @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = atom scheme json python scdl http server +SUBDIRS = scheme atom json scdl http server python java includedir = $(prefix)/include/modules nobase_include_HEADERS = */*.hpp diff --git a/sca-cpp/trunk/modules/atom/Makefile.am b/sca-cpp/trunk/modules/atom/Makefile.am index fa411b11a0..6629897b0b 100644 --- a/sca-cpp/trunk/modules/atom/Makefile.am +++ b/sca-cpp/trunk/modules/atom/Makefile.am @@ -17,10 +17,7 @@ noinst_PROGRAMS = atom-test -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} - atom_test_SOURCES = atom-test.cpp -atom_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +atom_test_LDADD = -lxml2 TESTS = atom-test - diff --git a/sca-cpp/trunk/modules/http/Makefile.am b/sca-cpp/trunk/modules/http/Makefile.am index 2f38513564..31af14086c 100644 --- a/sca-cpp/trunk/modules/http/Makefile.am +++ b/sca-cpp/trunk/modules/http/Makefile.am @@ -17,9 +17,9 @@ noinst_PROGRAMS = curl-test -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${JS_INCLUDE} -I${CURL_INCLUDE} +INCLUDES = -I${HTTPD_INCLUDE} curl_test_SOURCES = curl-test.cpp -curl_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${JS_LIB} -lmozjs +curl_test_LDADD = -lxml2 -lcurl -lmozjs TESTS = httpd-test http-test diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index e0c5d110c4..4a3e5d0f58 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -26,15 +26,11 @@ * HTTPD module implementation functions. */ -#include "string.hpp" -#include "stream.hpp" - #include "apr_strings.h" #include "apr_fnmatch.h" #include "apr_lib.h" #define APR_WANT_STRFUNC #include "apr_want.h" -#include "ap_config.h" #include "httpd.h" #include "http_config.h" @@ -48,9 +44,10 @@ #include "mod_core.h" +#include "string.hpp" +#include "stream.hpp" #include "list.hpp" #include "value.hpp" -#include "debug.hpp" namespace tuscany { @@ -120,7 +117,7 @@ const string contentType(const request_rec* r) { return optional(apr_table_get(r->headers_in, "Content-Type")); } -#ifdef _DEBUG +#ifdef WANT_MAINTAINER_MODE /** * Debug log. diff --git a/sca-cpp/trunk/modules/json/Makefile.am b/sca-cpp/trunk/modules/json/Makefile.am index c200060e56..3a3a477867 100644 --- a/sca-cpp/trunk/modules/json/Makefile.am +++ b/sca-cpp/trunk/modules/json/Makefile.am @@ -17,10 +17,7 @@ noinst_PROGRAMS = json-test -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${JS_INCLUDE} - json_test_SOURCES = json-test.cpp -json_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${JS_LIB} -lmozjs +json_test_LDADD = -lmozjs TESTS = json-test - diff --git a/sca-cpp/trunk/modules/python/Makefile.am b/sca-cpp/trunk/modules/python/Makefile.am index d61ca5bed3..a9a06c7b12 100644 --- a/sca-cpp/trunk/modules/python/Makefile.am +++ b/sca-cpp/trunk/modules/python/Makefile.am @@ -15,17 +15,31 @@ # specific language governing permissions and limitations # under the License. -noinst_PROGRAMS = python-test python-shell - datadir=$(prefix)/modules/python + +if WANT_PYTHON + +noinst_PROGRAMS = python-test python-shell client-test + +libdir=$(prefix)/lib +lib_LTLIBRARIES = libmod_tuscany_python.la + nobase_data_DATA = *.xsd -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${PYTHON_INCLUDE} +INCLUDES = -I${PYTHON_INCLUDE} + +libmod_tuscany_python_la_SOURCES = mod-python.cpp +libmod_tuscany_python_la_LIBADD = -lxml2 -lcurl -lmozjs -L${PYTHON_LIB} -lpython2.6 python_test_SOURCES = python-test.cpp -python_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6 +python_test_LDADD = -L${PYTHON_LIB} -lpython2.6 python_shell_SOURCES = python-shell.cpp -python_shell_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6 +python_shell_LDADD = -L${PYTHON_LIB} -lpython2.6 + +client_test_SOURCES = client-test.cpp +client_test_LDADD = -lxml2 -lcurl -lmozjs + +TESTS = python-test server-test -TESTS = python-test +endif
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/python/client-test.cpp b/sca-cpp/trunk/modules/python/client-test.cpp new file mode 100644 index 0000000000..b070f6a798 --- /dev/null +++ b/sca-cpp/trunk/modules/python/client-test.cpp @@ -0,0 +1,46 @@ +/* + * 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$ */ + +/** + * Test HTTP client functions. + */ + +#include "stream.hpp" +#include "string.hpp" +#include "../server/client-test.hpp" + +namespace tuscany { +namespace server { + +string testURI = "http://localhost:8090/python"; + +} +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::server::testServer(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/modules/server/client-test.py b/sca-cpp/trunk/modules/python/client-test.py index 24b78f83ca..24b78f83ca 100644 --- a/sca-cpp/trunk/modules/server/client-test.py +++ b/sca-cpp/trunk/modules/python/client-test.py diff --git a/sca-cpp/trunk/modules/python/domain-test.composite b/sca-cpp/trunk/modules/python/domain-test.composite new file mode 100644 index 0000000000..7318f96520 --- /dev/null +++ b/sca-cpp/trunk/modules/python/domain-test.composite @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200903" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://domain/test" + name="domain-test"> + + <component name="python-test"> + <t:implementation.python uri="server-test.py"/> + <service name="test"> + <t:binding.http uri="python"/> + </service> + </component> + + <component name="client-test"> + <t:implementation.python uri="client-test.py"/> + <service name="client"> + <t:binding.http uri="client"/> + </service> + <reference name="ref" target="python-test"> + <t:binding.http/> + </reference> + </component> + +</composite> diff --git a/sca-cpp/trunk/modules/python/htdocs/index.html b/sca-cpp/trunk/modules/python/htdocs/index.html new file mode 100644 index 0000000000..1bfb3e30c2 --- /dev/null +++ b/sca-cpp/trunk/modules/python/htdocs/index.html @@ -0,0 +1,21 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html><body><h1>It works!</h1></body></html> + diff --git a/sca-cpp/trunk/modules/python/mod-python.cpp b/sca-cpp/trunk/modules/python/mod-python.cpp new file mode 100644 index 0000000000..1352c50c11 --- /dev/null +++ b/sca-cpp/trunk/modules/python/mod-python.cpp @@ -0,0 +1,53 @@ +/* + * 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 eval Python component implementations. + */ + +#include "string.hpp" +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../server/mod-cpp.hpp" +#include "../server/mod-eval.hpp" +#include "mod-python.hpp" + +namespace tuscany { +namespace server { +namespace modeval { + +/** + * Return a configured component implementation. + * For now only Scheme and C++ implementations are supported. + */ +const failable<lambda<value(const list<value>&)> > readImplementation(const string& itype, const string& path, const list<value>& px) { + if (contains(itype, ".python")) + return modpython::readImplementation(path, px); + if (contains(itype, ".cpp")) + return modcpp::readImplementation(path, px); + return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); +} + +} +} +} diff --git a/sca-cpp/trunk/modules/server/mod-python.hpp b/sca-cpp/trunk/modules/python/mod-python.hpp index 219613d1e3..9f44e1d50c 100644 --- a/sca-cpp/trunk/modules/server/mod-python.hpp +++ b/sca-cpp/trunk/modules/python/mod-python.hpp @@ -34,7 +34,7 @@ #include "value.hpp" #include "debug.hpp" #include "monad.hpp" -#include "../python/eval.hpp" +#include "eval.hpp" #include "../http/httpd.hpp" namespace tuscany { diff --git a/sca-cpp/trunk/modules/python/python-conf b/sca-cpp/trunk/modules/python/python-conf new file mode 100755 index 0000000000..856237ed9d --- /dev/null +++ b/sca-cpp/trunk/modules/python/python-conf @@ -0,0 +1,29 @@ +#!/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 a server conf +here=`readlink -f $0`; here=`dirname $here` +root=`readlink -f $1` + +mkdir -p $root +mkdir -p $root/logs +mkdir -p $root/conf +cat >>$root/conf/httpd.conf <<EOF +LoadModule mod_tuscany_eval $here/.libs/libmod_tuscany_python.so +EOF diff --git a/sca-cpp/trunk/modules/python/server-test b/sca-cpp/trunk/modules/python/server-test new file mode 100755 index 0000000000..daa659cce3 --- /dev/null +++ b/sca-cpp/trunk/modules/python/server-test @@ -0,0 +1,42 @@ +#!/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. + +# Setup +../http/httpd-conf tmp 8090 htdocs +../server/server-conf tmp +./python-conf tmp +cat >>tmp/conf/httpd.conf <<EOF + +<Location /> +SCAContribution `pwd`/ +SCAComposite domain-test.composite +</Location> +EOF + +apachectl -k start -d `pwd`/tmp +sleep 2 + +# Test +./client-test 2>/dev/null +rc=$? + +# Cleanup +apachectl -k stop -d `pwd`/tmp +sleep 2 +return $rc diff --git a/sca-cpp/trunk/modules/server/server-test.py b/sca-cpp/trunk/modules/python/server-test.py index cdef94e116..cdef94e116 100644 --- a/sca-cpp/trunk/modules/server/server-test.py +++ b/sca-cpp/trunk/modules/python/server-test.py diff --git a/sca-cpp/trunk/modules/scdl/Makefile.am b/sca-cpp/trunk/modules/scdl/Makefile.am index a43b2a721e..b8f81fdf0b 100644 --- a/sca-cpp/trunk/modules/scdl/Makefile.am +++ b/sca-cpp/trunk/modules/scdl/Makefile.am @@ -17,10 +17,7 @@ noinst_PROGRAMS = scdl-test -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} - scdl_test_SOURCES = scdl-test.cpp -scdl_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +scdl_test_LDADD = -lxml2 TESTS = scdl-test - diff --git a/sca-cpp/trunk/modules/scheme/Makefile.am b/sca-cpp/trunk/modules/scheme/Makefile.am index ecf2a6e332..f9bfe4e392 100644 --- a/sca-cpp/trunk/modules/scheme/Makefile.am +++ b/sca-cpp/trunk/modules/scheme/Makefile.am @@ -20,13 +20,8 @@ noinst_PROGRAMS = eval-test eval-shell datadir=$(prefix)/modules/eval nobase_data_DATA = *.xsd -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} - eval_test_SOURCES = eval-test.cpp -eval_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 eval_shell_SOURCES = eval-shell.cpp -eval_shell_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 TESTS = eval-test - diff --git a/sca-cpp/trunk/modules/scheme/primitive.hpp b/sca-cpp/trunk/modules/scheme/primitive.hpp index 606cb309b5..f1396710f5 100644 --- a/sca-cpp/trunk/modules/scheme/primitive.hpp +++ b/sca-cpp/trunk/modules/scheme/primitive.hpp @@ -40,12 +40,12 @@ const value primitiveSymbol("primitive"); const value quoteSymbol("'"); const value lambdaSymbol("lambda"); -#ifdef _REENTRANT +#ifdef WANT_THREADS __thread #endif ostream* displayOutStream = NULL; -#ifdef _REENTRANT +#ifdef WANT_THREADS __thread #endif ostream* logOutStream = NULL; diff --git a/sca-cpp/trunk/modules/server/Makefile.am b/sca-cpp/trunk/modules/server/Makefile.am index 6b3e818090..f68fee9f4f 100644 --- a/sca-cpp/trunk/modules/server/Makefile.am +++ b/sca-cpp/trunk/modules/server/Makefile.am @@ -20,21 +20,20 @@ noinst_PROGRAMS = client-test libdir=$(prefix)/lib lib_LTLIBRARIES = libmod_tuscany_eval.la libmod_tuscany_wiring.la -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${JS_INCLUDE} -I${CURL_INCLUDE} +INCLUDES = -I${HTTPD_INCLUDE} libmod_tuscany_eval_la_SOURCES = mod-eval.cpp -libmod_tuscany_eval_la_LIBADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${JS_LIB} -lmozjs -L${PYTHON_LIB} -lpython2.6 +libmod_tuscany_eval_la_LIBADD = -lxml2 -lcurl -lmozjs libmod_tuscany_wiring_la_SOURCES = mod-wiring.cpp -libmod_tuscany_wiring_la_LIBADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${JS_LIB} -lmozjs +libmod_tuscany_wiring_la_LIBADD = -lxml2 -lcurl -lmozjs testdir=$(prefix)/test test_LTLIBRARIES = libimpl-test.la libimpl_test_la_SOURCES = impl-test.cpp -libimpl_test_la_LIBADD = -L${APR_LIB} -lapr-1 -laprutil-1 client_test_SOURCES = client-test.cpp -client_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${JS_LIB} -lmozjs +client_test_LDADD = -lxml2 -lcurl -lmozjs TESTS = httpd-test server-test wiring-test diff --git a/sca-cpp/trunk/modules/server/client-test.cpp b/sca-cpp/trunk/modules/server/client-test.cpp index 557dfaf59e..3bc8aa7d10 100644 --- a/sca-cpp/trunk/modules/server/client-test.cpp +++ b/sca-cpp/trunk/modules/server/client-test.cpp @@ -23,364 +23,14 @@ * Test HTTP client functions. */ -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <assert.h> #include "stream.hpp" #include "string.hpp" -#include "parallel.hpp" -#include "perf.hpp" -#include "../http/curl.hpp" +#include "client-test.hpp" namespace tuscany { namespace server { -ostream* curlWriter(const string& s, ostream* os) { - (*os) << s; - return os; -} - -const bool testGet() { - gc_scoped_pool pool; - http::CURLSession ch; - { - ostringstream os; - const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090", ch); - assert(hasContent(r)); - assert(contains(str(os), "HTTP/1.1 200 OK")); - assert(contains(str(os), "It works")); - } - { - const failable<value> r = http::getcontent("http://localhost:8090", ch); - assert(hasContent(r)); - assert(contains(car(reverse(list<value>(content(r)))), "It works")); - } - return true; -} - -struct getLoop { - http::CURLSession ch; - getLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { - const failable<value> r = http::getcontent("http://localhost:8090", ch); - assert(hasContent(r)); - assert(contains(car(reverse(list<value>(content(r)))), "It works")); - return true; - } -}; - -const bool testGetPerf() { - gc_scoped_pool pool; - http::CURLSession ch; - const lambda<bool()> gl = getLoop(ch); - cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; - return true; -} - -const bool testEval(const string& uri) { - gc_scoped_pool pool; - http::CURLSession ch; - const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch)); - assert(val == string("Hello")); - return true; -} - -const bool testEval() { - testEval("http://localhost:8090/test"); - testEval("http://localhost:8090/cpp"); - testEval("http://localhost:8090/python"); - return true; -} - -struct evalLoop { - const string uri; - http::CURLSession ch; - evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch)); - assert(val == string("Hello")); - return true; - } -}; - -const value blob(string(3000, 'A')); -const list<value> blobs = mklist(blob, blob, blob, blob, blob); - -struct blobEvalLoop { - const string uri; - http::CURLSession ch; - blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch)); - assert(val == blobs); - return true; - } -}; - -const bool testEvalPerf(const string& type, const string& uri) { - gc_scoped_pool pool; - http::CURLSession ch; - const lambda<bool()> el = evalLoop(uri, ch); - cout << type << " JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; - const lambda<bool()> bel = blobEvalLoop(uri, ch); - cout << type << " JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; - return true; -} - -const bool testEvalPerf() { - testEvalPerf("Scheme", "http://localhost:8090/test"); - testEvalPerf("C++", "http://localhost:8090/cpp"); - testEvalPerf("Python", "http://localhost:8090/python"); - return true; -} - -bool testPost(const string& uri) { - gc_scoped_pool pool; - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99")); - const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession ch; - const failable<value> id = http::post(a, uri, ch); - assert(hasContent(id)); - return true; -} - -const bool testPost() { - testPost("http://localhost:8090/test"); - testPost("http://localhost:8090/cpp"); - testPost("http://localhost:8090/python"); - return true; -} - -struct postLoop { - const string uri; - const value val; - http::CURLSession ch; - postLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - const failable<value> id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - -struct postBlobLoop { - const string uri; - const value val; - http::CURLSession ch; - postBlobLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - gc_scoped_pool pool; - const failable<value> id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - -const bool testPostPerf(const string& type, const string& uri) { - gc_scoped_pool pool; - http::CURLSession ch; - { - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99")); - const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - const lambda<bool()> pl = postLoop(uri, val, ch); - cout << type << " ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; - } - { - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "blob1" + blob) - + (list<value>() + "blob2" + blob) - + (list<value>() + "blob3" + blob) - + (list<value>() + "blob4" + blob) - + (list<value>() + "blob5" + blob) - + (list<value>() + "price" + string("$2.99")); - const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - const lambda<bool()> pl = postBlobLoop(uri, val, ch); - cout << type << " ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; - } - return true; -} - -const bool testPostPerf() { - testPostPerf("Scheme", "http://localhost:8090/test"); - testPostPerf("C++", "http://localhost:8090/cpp"); - testPostPerf("Python", "http://localhost:8090/python"); - return true; -} - -#ifdef WANT_THREADS - -const bool postThread(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch; - const lambda<bool()> pl = postLoop(uri, val, ch); - time(pl, 0, count); - return true; -} - -const list<future<bool> > startPost(worker& w, const int threads, const lambda<bool()>& l) { - if (threads == 0) - return list<future<bool> >(); - return cons(submit(w, l), startPost(w, threads - 1, l)); -} - -const bool checkPost(const list<future<bool> >& r) { - if (isNil(r)) - return true; - assert(car(r) == true); - return checkPost(cdr(r)); -} - -struct postThreadLoop { - const lambda<bool()> l; - const int threads; - const gc_ptr<worker> w; - postThreadLoop(const lambda<bool()>& l, const int threads) : l(l), threads(threads), w(new (gc_new<worker>()) worker(threads)) { - } - const bool operator()() const { - list<future<bool> > r = startPost(*w, threads, l); - checkPost(r); - return true; - } -}; - -const bool testPostThreadPerf(const string& type, const string& uri) { - gc_scoped_pool pool; - const int count = 50; - const int threads = 10; - - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99")); - const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - - const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), uri, count, val); - const lambda<bool()> ptl = postThreadLoop(pl, threads); - double t = time(ptl, 0, 1) / (threads * count); - cout << type << " ATOMPub POST thread test " << t << " ms" << endl; - - return true; -} - -const bool testPostThreadPerf() { - testPostThreadPerf("Scheme", "http://localhost:8090/test"); - testPostThreadPerf("C++", "http://localhost:8090/cpp"); - testPostThreadPerf("Python", "http://localhost:8090/python"); - return true; -} - -#else - -const bool postProc(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch; - const lambda<bool()> pl = postLoop(uri, val, ch); - time(pl, 0, count); - return true; -} - -const list<pid_t> startPost(const int procs, const lambda<bool()>& l) { - if (procs == 0) - return list<pid_t>(); - pid_t pid = fork(); - if (pid == 0) { - assert(l() == true); - exit(0); - } - return cons(pid, startPost(procs - 1, l)); -} - -const bool checkPost(const list<pid_t>& r) { - if (isNil(r)) - return true; - int status; - waitpid(car(r), &status, 0); - assert(status == 0); - return checkPost(cdr(r)); -} - -struct postForkLoop { - const lambda<bool()> l; - const int procs; - postForkLoop(const lambda<bool()>& l, const int procs) : l(l), procs(procs) { - } - const bool operator()() const { - list<pid_t> r = startPost(procs, l); - checkPost(r); - return true; - } -}; - -const bool testPostForkPerf(const string& type, const string& uri) { - gc_scoped_pool pool; - const int count = 50; - const int procs = 10; - - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99")); - const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - - const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postProc), uri, count, val); - const lambda<bool()> ptl = postForkLoop(pl, procs); - double t = time(ptl, 0, 1) / (procs * count); - cout << type << "ATOMPub POST fork test " << t << " ms" << endl; - - return true; -} - -const bool testPostForkPerf() { - testPostForkPerf("Scheme", "http://localhost:8090/test"); - testPostForkPerf("C++", "http://localhost:8090/cpp"); - testPostForkPerf("Python", "http://localhost:8090/python"); - return true; -} - -#endif - -const bool testPut(const string& uri) { - gc_scoped_pool pool; - const list<value> i = list<value>() - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99")); - const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLSession ch; - value rc = content(http::put(a, uri, ch)); - assert(rc == value(true)); - return true; -} - -const bool testPut() { - testPut("http://localhost:8090/test/111"); - testPut("http://localhost:8090/cpp/111"); - testPut("http://localhost:8090/python/111"); - return true; -} - -const bool testDel(const string& uri) { - gc_scoped_pool pool; - http::CURLSession ch; - value rc = content(http::del(uri, ch)); - assert(rc == value(true)); - return true; -} - -const bool testDel() { - testDel("http://localhost:8090/test/123456789"); - testDel("http://localhost:8090/cpp/123456789"); - testDel("http://localhost:8090/python/123456789"); - return true; -} +string testURI = "http://localhost:8090/test"; } } @@ -388,19 +38,7 @@ const bool testDel() { int main() { tuscany::cout << "Testing..." << tuscany::endl; - tuscany::server::testGet(); - tuscany::server::testPost(); - tuscany::server::testPut(); - tuscany::server::testDel(); - tuscany::server::testEval(); - tuscany::server::testGetPerf(); - tuscany::server::testPostPerf(); -#ifdef WANT_THREADS - tuscany::server::testPostThreadPerf(); -#else - tuscany::server::testPostForkPerf(); -#endif - tuscany::server::testEvalPerf(); + tuscany::server::testServer(); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp new file mode 100644 index 0000000000..d1c8d9ba15 --- /dev/null +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -0,0 +1,349 @@ +/* + * 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$ */ + +/** + * Test HTTP client functions. + */ + +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <assert.h> +#include "stream.hpp" +#include "string.hpp" +#include "parallel.hpp" +#include "perf.hpp" +#include "../http/curl.hpp" + +namespace tuscany { +namespace server { + +extern string testURI; + +ostream* curlWriter(const string& s, ostream* os) { + (*os) << s; + return os; +} + +const bool testGet() { + gc_scoped_pool pool; + http::CURLSession ch; + { + ostringstream os; + const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090", ch); + assert(hasContent(r)); + assert(contains(str(os), "HTTP/1.1 200 OK")); + assert(contains(str(os), "It works")); + } + { + const failable<value> r = http::getcontent("http://localhost:8090", ch); + assert(hasContent(r)); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); + } + return true; +} + +struct getLoop { + http::CURLSession ch; + getLoop(http::CURLSession& ch) : ch(ch) { + } + const bool operator()() const { + const failable<value> r = http::getcontent("http://localhost:8090", ch); + assert(hasContent(r)); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); + return true; + } +}; + +const bool testGetPerf() { + gc_scoped_pool pool; + http::CURLSession ch; + const lambda<bool()> gl = getLoop(ch); + cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; + return true; +} + +const bool testEval() { + gc_scoped_pool pool; + http::CURLSession ch; + const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch)); + assert(val == string("Hello")); + return true; +} + +struct evalLoop { + const string uri; + http::CURLSession ch; + evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { + } + const bool operator()() const { + const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch)); + assert(val == string("Hello")); + return true; + } +}; + +const value blob(string(3000, 'A')); +const list<value> blobs = mklist(blob, blob, blob, blob, blob); + +struct blobEvalLoop { + const string uri; + http::CURLSession ch; + blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { + } + const bool operator()() const { + const value val = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch)); + assert(val == blobs); + return true; + } +}; + +const bool testEvalPerf() { + gc_scoped_pool pool; + http::CURLSession ch; + const lambda<bool()> el = evalLoop(testURI, ch); + cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; + const lambda<bool()> bel = blobEvalLoop(testURI, ch); + cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; + return true; +} + +bool testPost() { + gc_scoped_pool pool; + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + http::CURLSession ch; + const failable<value> id = http::post(a, testURI, ch); + assert(hasContent(id)); + return true; +} + +struct postLoop { + const string uri; + const value val; + http::CURLSession ch; + postLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { + } + const bool operator()() const { + const failable<value> id = http::post(val, uri, ch); + assert(hasContent(id)); + return true; + } +}; + +struct postBlobLoop { + const string uri; + const value val; + http::CURLSession ch; + postBlobLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { + } + const bool operator()() const { + gc_scoped_pool pool; + const failable<value> id = http::post(val, uri, ch); + assert(hasContent(id)); + return true; + } +}; + +const bool testPostPerf() { + gc_scoped_pool pool; + http::CURLSession ch; + { + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + const lambda<bool()> pl = postLoop(testURI, val, ch); + cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; + } + { + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "blob1" + blob) + + (list<value>() + "blob2" + blob) + + (list<value>() + "blob3" + blob) + + (list<value>() + "blob4" + blob) + + (list<value>() + "blob5" + blob) + + (list<value>() + "price" + string("$2.99")); + const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + const lambda<bool()> pl = postBlobLoop(testURI, val, ch); + cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; + } + return true; +} + +#ifdef WANT_THREADS + +const bool postThread(const string& uri, const int count, const value& val) { + gc_scoped_pool pool; + http::CURLSession ch; + const lambda<bool()> pl = postLoop(uri, val, ch); + time(pl, 0, count); + return true; +} + +const list<future<bool> > startPost(worker& w, const int threads, const lambda<bool()>& l) { + if (threads == 0) + return list<future<bool> >(); + return cons(submit(w, l), startPost(w, threads - 1, l)); +} + +const bool checkPost(const list<future<bool> >& r) { + if (isNil(r)) + return true; + assert(car(r) == true); + return checkPost(cdr(r)); +} + +struct postThreadLoop { + const lambda<bool()> l; + const int threads; + const gc_ptr<worker> w; + postThreadLoop(const lambda<bool()>& l, const int threads) : l(l), threads(threads), w(new (gc_new<worker>()) worker(threads)) { + } + const bool operator()() const { + list<future<bool> > r = startPost(*w, threads, l); + checkPost(r); + return true; + } +}; + +const bool testPostThreadPerf() { + gc_scoped_pool pool; + const int count = 50; + const int threads = 10; + + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), testURI, count, val); + const lambda<bool()> ptl = postThreadLoop(pl, threads); + double t = time(ptl, 0, 1) / (threads * count); + cout << "ATOMPub POST thread test " << t << " ms" << endl; + + return true; +} + +#else + +const bool postProc(const string& uri, const int count, const value& val) { + gc_scoped_pool pool; + http::CURLSession ch; + const lambda<bool()> pl = postLoop(uri, val, ch); + time(pl, 0, count); + return true; +} + +const list<pid_t> startPost(const int procs, const lambda<bool()>& l) { + if (procs == 0) + return list<pid_t>(); + pid_t pid = fork(); + if (pid == 0) { + assert(l() == true); + exit(0); + } + return cons(pid, startPost(procs - 1, l)); +} + +const bool checkPost(const list<pid_t>& r) { + if (isNil(r)) + return true; + int status; + waitpid(car(r), &status, 0); + assert(status == 0); + return checkPost(cdr(r)); +} + +struct postForkLoop { + const lambda<bool()> l; + const int procs; + postForkLoop(const lambda<bool()>& l, const int procs) : l(l), procs(procs) { + } + const bool operator()() const { + list<pid_t> r = startPost(procs, l); + checkPost(r); + return true; + } +}; + +const bool testPostForkPerf() { + gc_scoped_pool pool; + const int count = 50; + const int procs = 10; + + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postProc), testURI, count, val); + const lambda<bool()> ptl = postForkLoop(pl, procs); + double t = time(ptl, 0, 1) / (procs * count); + cout << "ATOMPub POST fork test " << t << " ms" << endl; + + return true; +} + +#endif + +const bool testPut() { + gc_scoped_pool pool; + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + http::CURLSession ch; + value rc = content(http::put(a, testURI, ch)); + assert(rc == value(true)); + return true; +} + +const bool testDel() { + gc_scoped_pool pool; + http::CURLSession ch; + value rc = content(http::del(testURI, ch)); + assert(rc == value(true)); + return true; +} + +const bool testServer() { + tuscany::server::testGet(); + tuscany::server::testPost(); + tuscany::server::testPut(); + tuscany::server::testDel(); + tuscany::server::testEval(); + tuscany::server::testGetPerf(); + tuscany::server::testPostPerf(); +#ifdef WANT_THREADS + tuscany::server::testPostThreadPerf(); +#else + tuscany::server::testPostForkPerf(); +#endif + tuscany::server::testEvalPerf(); + return true; +} + +} +} diff --git a/sca-cpp/trunk/modules/server/domain-test.composite b/sca-cpp/trunk/modules/server/domain-test.composite index c911e9cf07..d5b0dae511 100644 --- a/sca-cpp/trunk/modules/server/domain-test.composite +++ b/sca-cpp/trunk/modules/server/domain-test.composite @@ -36,16 +36,8 @@ </service> </component> - <component name="python-test"> - <t:implementation.python uri="server-test.py"/> - <service name="test"> - <t:binding.http uri="python"/> - </service> - </component> - <component name="client-test"> - <!-- <t:implementation.scheme uri="client-test.scm"/> --> - <t:implementation.python uri="client-test.py"/> + <t:implementation.scheme uri="client-test.scm"/> <service name="client"> <t:binding.http uri="client"/> </service> diff --git a/sca-cpp/trunk/modules/server/httpd-test b/sca-cpp/trunk/modules/server/httpd-test index 7dccfbf112..79651c8351 100755 --- a/sca-cpp/trunk/modules/server/httpd-test +++ b/sca-cpp/trunk/modules/server/httpd-test @@ -22,6 +22,7 @@ echo "Testing..." # Setup ../http/httpd-conf tmp 8090 htdocs ./server-conf tmp +./scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> diff --git a/sca-cpp/trunk/modules/server/impl-test.cpp b/sca-cpp/trunk/modules/server/impl-test.cpp index 1fd432c7fb..ad8953bf12 100644 --- a/sca-cpp/trunk/modules/server/impl-test.cpp +++ b/sca-cpp/trunk/modules/server/impl-test.cpp @@ -29,7 +29,6 @@ #include "list.hpp" #include "value.hpp" #include "monad.hpp" -#include "debug.hpp" namespace tuscany { namespace server { diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp index 93abd84590..416ccabf39 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -33,7 +33,6 @@ #include "function.hpp" #include "list.hpp" #include "value.hpp" -#include "debug.hpp" #include "monad.hpp" #include "dynlib.hpp" #include "../scheme/driver.hpp" diff --git a/sca-cpp/trunk/modules/server/mod-eval.cpp b/sca-cpp/trunk/modules/server/mod-eval.cpp index 23454e3ceb..936c68d70f 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.cpp +++ b/sca-cpp/trunk/modules/server/mod-eval.cpp @@ -20,418 +20,34 @@ /* $Rev$ $Date$ */ /** - * HTTPD module used to eval component implementations. + * HTTPD module used to eval C++ and Scheme component implementations. */ #include "string.hpp" -#include "stream.hpp" #include "function.hpp" #include "list.hpp" -#include "tree.hpp" #include "value.hpp" -#include "element.hpp" #include "monad.hpp" -#include "../atom/atom.hpp" -#include "../json/json.hpp" -#include "../scdl/scdl.hpp" -#include "../http/curl.hpp" -#include "../http/httpd.hpp" +#include "mod-eval.hpp" #include "mod-scheme.hpp" #include "mod-cpp.hpp" -#include "mod-python.hpp" - -extern "C" { -extern module AP_MODULE_DECLARE_DATA mod_tuscany_eval; -} namespace tuscany { namespace server { namespace modeval { /** - * Server configuration. - */ -class ServerConf { -public: - ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") { - } - - const server_rec* s; - string home; - string wiringServerName; -}; - -/** - * Directory configuration. - */ -class DirConf { -public: - DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName("") { - } - const char* dirspec; - string contributionPath; - string compositeName; - list<value> implementations; -}; - -/** - * Convert a result represented as a content + failure pair to a - * failable monad. - */ -const failable<value> failableResult(const list<value>& v) { - if (isNil(cdr(v))) - return car(v); - return mkfailure<value>(string(cadr(v))); -} - -/** - * Handle an HTTP GET. - */ -const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& impl) { - debug(r->uri, "modeval::get::uri"); - - // Inspect the query string - const list<list<value> > args = httpd::queryArgs(r); - const list<value> ia = assoc(value("id"), args); - const list<value> ma = assoc(value("method"), args); - - // Evaluate a JSON-RPC request and return a JSON result - if (!isNil(ia) && !isNil(ma)) { - - // Extract the request id, method and params - const value id = cadr(ia); - const value func = c_str(json::funcName(string(cadr(ma)))); - - // Apply the requested function - const failable<value> val = failableResult(impl(cons(func, httpd::queryParams(args)))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - - // Return JSON result - json::JSONContext cx; - return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc", r); - } - - // Evaluate an ATOM GET request and return an ATOM feed representing a collection of resources - const list<value> path(httpd::pathValues(r->uri)); - if (isNil(cddr(path))) { - const failable<value> val = failableResult(impl(cons<value>("getall", list<value>()))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(content(val))), "application/atom+xml;type=feed", r); - } - - // Evaluate an ATOM GET and return an ATOM entry representing a resource - const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(caddr(path))))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(content(val))), "application/atom+xml;type=entry", r); -} - -/** - * 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")) { - json::JSONContext cx; - const list<value> json = elementsToValues(content(json::readJSON(ls, cx))); - const list<list<value> > args = httpd::postArgs(json); - - // Extract the request id, method and params - const value id = cadr(assoc(value("id"), args)); - const value func = c_str(json::funcName(cadr(assoc(value("method"), args)))); - const list<value> params = (list<value>)cadr(assoc(value("params"), args)); - - // Evaluate the request expression - const failable<value> val = failableResult(impl(cons<value>(func, params))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - - // Return JSON result - return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc", r); - } - - // Evaluate an ATOM POST request and return the location of the corresponding created resource - if (contains(ct, "application/atom+xml")) { - - // Evaluate the request expression - const value entry = atom::entryValue(content(atom::readEntry(ls))); - const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(entry)))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - - // Return the created resource location - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, httpd::url(content(val), r))); - r->status = HTTP_CREATED; - return OK; - } - - return HTTP_NOT_IMPLEMENTED; -} - -/** - * 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 - const list<value> path(httpd::pathValues(r->uri)); - const value entry = atom::entryValue(content(atom::readEntry(ls))); - const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry)))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - if (val == value(false)) - return HTTP_NOT_FOUND; - return OK; -} - -/** - * Handle an HTTP DELETE. - */ -const failable<int> del(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(httpd::pathValues(r->uri)); - if (isNil(cddr(path))) { - - // Delete a collection of resources - const failable<value> val = failableResult(impl(cons<value>("deleteall", list<value>()))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - if (val == value(false)) - return HTTP_NOT_FOUND; - return OK; - } - - // Delete a resource - const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(caddr(path))))); - if (!hasContent(val)) - return mkfailure<int>(reason(val)); - if (val == value(false)) - return HTTP_NOT_FOUND; - return OK; -} - -/** - * Translate a component request. - */ -int translate(request_rec *r) { - gc_scoped_pool pool(r->pool); - if (strncmp(r->uri, "/components/", 12) != 0) - return DECLINED; - r->handler = "mod_tuscany_eval"; - return OK; -} - -/** - * HTTP request handler. - */ -int handler(request_rec *r) { - gc_scoped_pool pool(r->pool); - if(strcmp(r->handler, "mod_tuscany_eval")) - 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)); - const list<value> impl(assoctree<value>(cadr(path), dc.implementations)); - if (isNil(impl)) - return HTTP_NOT_FOUND; - - // Handle HTTP method - const lambda<value(const list<value>&)> l(cadr<value>(impl)); - if (r->header_only) - return OK; - if(r->method_number == M_GET) - return httpd::reportStatus(get(r, l)); - if(r->method_number == M_POST) - return httpd::reportStatus(post(r, l)); - if(r->method_number == M_PUT) - return httpd::reportStatus(put(r, l)); - if(r->method_number == M_DELETE) - return httpd::reportStatus(del(r, l)); - return HTTP_NOT_IMPLEMENTED; -} - -/** - * Convert a list of component references to a list of HTTP proxy lambdas. - */ -const value mkproxy(const value& ref, const string& base) { - return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)))); -} - -const list<value> proxies(const list<value>& refs, const string& base) { - if (isNil(refs)) - return refs; - return cons(mkproxy(car(refs), base), proxies(cdr(refs), base)); -} - -/** * Return a configured component implementation. * For now only Scheme and C++ implementations are supported. */ const failable<lambda<value(const list<value>&)> > readImplementation(const string& itype, const string& path, const list<value>& px) { if (contains(itype, ".scheme")) return modscheme::readImplementation(path, px); - if (contains(itype, ".python")) - return modpython::readImplementation(path, px); if (contains(itype, ".cpp")) return modcpp::readImplementation(path, px); return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); } -const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server, const value& comp) { - const value impl = scdl::implementation(comp); - const string path = dc.contributionPath + string(scdl::uri(impl)); - - // Convert component references to configured proxy lambdas - ostringstream base; - if (sc.wiringServerName == "") - base << (server.server_scheme == NULL? "http" : server.server_scheme) - << "://" << (server.server_hostname == NULL? "localhost" : server.server_hostname) - << ":" << (server.port == 0? 80 : server.port) - << "/references/" << string(scdl::name(comp)) << "/"; - else - base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/"; - const list<value> px(proxies(scdl::references(comp), str(base))); - - // Read and configure the implementation - const failable<lambda<value(const list<value>&)> > cimpl(readImplementation(elementName(impl), path, px)); - if (!hasContent(cimpl)) - return reason(cimpl); - return content(cimpl); } - -/** - * Return a tree of component-name + configured-implementation pairs. - */ -const list<value> componentToImplementationAssoc(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) { - if (isNil(c)) - return c; - return cons<value>(mklist<value>(scdl::name(car(c)), confImplementation(dc, sc, server, car(c))), componentToImplementationAssoc(dc, sc, server, cdr(c))); -} - -const list<value> componentToImplementationTree(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) { - return mkbtree(sort(componentToImplementationAssoc(dc, sc, server, c))); } - -/** - * Read the components declared in a composite. - */ -const failable<list<value> > readComponents(const string& path) { - ifstream is(path); - if (fail(is)) - return mkfailure<list<value> >(string("Could not read composite: ") + path); - return scdl::components(readXML(streamList(is))); -} - -/** - * Configure the components declared in the deployed composite. - */ -const bool confComponents(DirConf& dc, ServerConf& sc, server_rec& server) { - if (dc.contributionPath == "" || dc.compositeName == "") - return true; - const failable<list<value> > comps = readComponents(dc.contributionPath + dc.compositeName); - if (!hasContent(comps)) - return true; - dc.implementations = componentToImplementationTree(dc, sc, server, content(comps)); - debug(dc.implementations, "modeval::confComponents::implementations"); - return true; -} - -/** - * Configuration commands. - */ -const char *confHome(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.home = arg; - return NULL; -} -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, void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); - ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - DirConf& dc = *(DirConf*)c; - dc.contributionPath = arg; - confComponents(dc, sc, *cmd->server); - return NULL; -} -const char *confComposite(cmd_parms *cmd, void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); - ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - DirConf& dc = *(DirConf*)c; - dc.compositeName = arg; - confComponents(dc, sc, *cmd->server); - return NULL; -} - -/** - * HTTP server module declaration. - */ -const command_rec commands[] = { - AP_INIT_TAKE1("TuscanyHome", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"), - AP_INIT_TAKE1("SCAWiringServerName", (const char*(*)())confWiringServerName, NULL, RSRC_CONF, "SCA wiring server name"), - 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, NULL, NULL, 0, NO_ARGS, NULL} -}; - -int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, unused server_rec *s) { - return OK; -} - -void childInit(apr_pool_t* p, server_rec* svr_rec) { - gc_scoped_pool pool(p); - ServerConf* c = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_eval); - if(c == NULL) { - cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; - exit(APEXIT_CHILDFATAL); - } -} - -void registerHooks(unused 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_eval = { - STANDARD20_MODULE_STUFF, - // dir config and merger - tuscany::httpd::makeDirConf<tuscany::server::modeval::DirConf>, NULL, - // server config and merger - tuscany::httpd::makeServerConf<tuscany::server::modeval::ServerConf>, NULL, - // commands and hooks - tuscany::server::modeval::commands, tuscany::server::modeval::registerHooks -}; - } diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp new file mode 100644 index 0000000000..4f95977fea --- /dev/null +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -0,0 +1,422 @@ +/* + * 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 eval component implementations. + */ + +#include "string.hpp" +#include "stream.hpp" +#include "function.hpp" +#include "list.hpp" +#include "tree.hpp" +#include "value.hpp" +#include "element.hpp" +#include "monad.hpp" +#include "../atom/atom.hpp" +#include "../json/json.hpp" +#include "../scdl/scdl.hpp" +#include "../http/curl.hpp" +#include "../http/httpd.hpp" + +extern "C" { +extern module AP_MODULE_DECLARE_DATA mod_tuscany_eval; +} + +namespace tuscany { +namespace server { +namespace modeval { + +/** + * Server configuration. + */ +class ServerConf { +public: + ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") { + } + + const server_rec* s; + string home; + string wiringServerName; +}; + +/** + * Directory configuration. + */ +class DirConf { +public: + DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName("") { + } + const char* dirspec; + string contributionPath; + string compositeName; + list<value> implementations; +}; + +/** + * Convert a result represented as a content + failure pair to a + * failable monad. + */ +const failable<value> failableResult(const list<value>& v) { + if (isNil(cdr(v))) + return car(v); + return mkfailure<value>(string(cadr(v))); +} + +/** + * Handle an HTTP GET. + */ +const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& impl) { + debug(r->uri, "modeval::get::uri"); + + // Inspect the query string + const list<list<value> > args = httpd::queryArgs(r); + const list<value> ia = assoc(value("id"), args); + const list<value> ma = assoc(value("method"), args); + + // Evaluate a JSON-RPC request and return a JSON result + if (!isNil(ia) && !isNil(ma)) { + + // Extract the request id, method and params + const value id = cadr(ia); + const value func = c_str(json::funcName(string(cadr(ma)))); + + // Apply the requested function + const failable<value> val = failableResult(impl(cons(func, httpd::queryParams(args)))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + + // Return JSON result + json::JSONContext cx; + return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc", r); + } + + // Evaluate an ATOM GET request and return an ATOM feed representing a collection of resources + const list<value> path(httpd::pathValues(r->uri)); + if (isNil(cddr(path))) { + const failable<value> val = failableResult(impl(cons<value>("getall", list<value>()))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(content(val))), "application/atom+xml;type=feed", r); + } + + // Evaluate an ATOM GET and return an ATOM entry representing a resource + const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(caddr(path))))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(content(val))), "application/atom+xml;type=entry", r); +} + +/** + * 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")) { + json::JSONContext cx; + const list<value> json = elementsToValues(content(json::readJSON(ls, cx))); + const list<list<value> > args = httpd::postArgs(json); + + // Extract the request id, method and params + const value id = cadr(assoc(value("id"), args)); + const value func = c_str(json::funcName(cadr(assoc(value("method"), args)))); + const list<value> params = (list<value>)cadr(assoc(value("params"), args)); + + // Evaluate the request expression + const failable<value> val = failableResult(impl(cons<value>(func, params))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + + // Return JSON result + return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc", r); + } + + // Evaluate an ATOM POST request and return the location of the corresponding created resource + if (contains(ct, "application/atom+xml")) { + + // Evaluate the request expression + const value entry = atom::entryValue(content(atom::readEntry(ls))); + const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(entry)))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + + // Return the created resource location + apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, httpd::url(content(val), r))); + r->status = HTTP_CREATED; + return OK; + } + + return HTTP_NOT_IMPLEMENTED; +} + +/** + * 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 + const list<value> path(httpd::pathValues(r->uri)); + const value entry = atom::entryValue(content(atom::readEntry(ls))); + const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry)))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + if (val == value(false)) + return HTTP_NOT_FOUND; + return OK; +} + +/** + * Handle an HTTP DELETE. + */ +const failable<int> del(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(httpd::pathValues(r->uri)); + if (isNil(cddr(path))) { + + // Delete a collection of resources + const failable<value> val = failableResult(impl(cons<value>("deleteall", list<value>()))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + if (val == value(false)) + return HTTP_NOT_FOUND; + return OK; + } + + // Delete a resource + const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(caddr(path))))); + if (!hasContent(val)) + return mkfailure<int>(reason(val)); + if (val == value(false)) + return HTTP_NOT_FOUND; + return OK; +} + +/** + * Translate a component request. + */ +int translate(request_rec *r) { + gc_scoped_pool pool(r->pool); + if (strncmp(r->uri, "/components/", 12) != 0) + return DECLINED; + r->handler = "mod_tuscany_eval"; + return OK; +} + +/** + * HTTP request handler. + */ +int handler(request_rec *r) { + gc_scoped_pool pool(r->pool); + if(strcmp(r->handler, "mod_tuscany_eval")) + 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)); + const list<value> impl(assoctree<value>(cadr(path), dc.implementations)); + if (isNil(impl)) + return HTTP_NOT_FOUND; + + // Handle HTTP method + const lambda<value(const list<value>&)> l(cadr<value>(impl)); + if (r->header_only) + return OK; + if(r->method_number == M_GET) + return httpd::reportStatus(get(r, l)); + if(r->method_number == M_POST) + return httpd::reportStatus(post(r, l)); + if(r->method_number == M_PUT) + return httpd::reportStatus(put(r, l)); + if(r->method_number == M_DELETE) + return httpd::reportStatus(del(r, l)); + return HTTP_NOT_IMPLEMENTED; +} + +/** + * Convert a list of component references to a list of HTTP proxy lambdas. + */ +const value mkproxy(const value& ref, const string& base) { + return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)))); +} + +const list<value> proxies(const list<value>& refs, const string& base) { + if (isNil(refs)) + return refs; + return cons(mkproxy(car(refs), base), proxies(cdr(refs), base)); +} + +extern const failable<lambda<value(const list<value>&)> > readImplementation(const string& itype, const string& path, const list<value>& px); + +const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server, const value& comp) { + const value impl = scdl::implementation(comp); + const string path = dc.contributionPath + string(scdl::uri(impl)); + + // Convert component references to configured proxy lambdas + ostringstream base; + if (sc.wiringServerName == "") + base << (server.server_scheme == NULL? "http" : server.server_scheme) + << "://" << (server.server_hostname == NULL? "localhost" : server.server_hostname) + << ":" << (server.port == 0? 80 : server.port) + << "/references/" << string(scdl::name(comp)) << "/"; + else + base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/"; + const list<value> px(proxies(scdl::references(comp), str(base))); + + // Read and configure the implementation + const failable<lambda<value(const list<value>&)> > cimpl(readImplementation(elementName(impl), path, px)); + if (!hasContent(cimpl)) + return reason(cimpl); + return content(cimpl); +} + +/** + * Return a tree of component-name + configured-implementation pairs. + */ +const list<value> componentToImplementationAssoc(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) { + if (isNil(c)) + return c; + return cons<value>(mklist<value>(scdl::name(car(c)), confImplementation(dc, sc, server, car(c))), componentToImplementationAssoc(dc, sc, server, cdr(c))); +} + +const list<value> componentToImplementationTree(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) { + return mkbtree(sort(componentToImplementationAssoc(dc, sc, server, c))); +} + +/** + * Read the components declared in a composite. + */ +const failable<list<value> > readComponents(const string& path) { + ifstream is(path); + if (fail(is)) + return mkfailure<list<value> >(string("Could not read composite: ") + path); + return scdl::components(readXML(streamList(is))); +} + +/** + * Configure the components declared in the deployed composite. + */ +const bool confComponents(DirConf& dc, ServerConf& sc, server_rec& server) { + if (dc.contributionPath == "" || dc.compositeName == "") + return true; + const failable<list<value> > comps = readComponents(dc.contributionPath + dc.compositeName); + if (!hasContent(comps)) + return true; + dc.implementations = componentToImplementationTree(dc, sc, server, content(comps)); + debug(dc.implementations, "modeval::confComponents::implementations"); + return true; +} + +/** + * Configuration commands. + */ +const char *confHome(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.home = arg; + return NULL; +} +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, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); + DirConf& dc = *(DirConf*)c; + dc.contributionPath = arg; + confComponents(dc, sc, *cmd->server); + return NULL; +} +const char *confComposite(cmd_parms *cmd, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); + DirConf& dc = *(DirConf*)c; + dc.compositeName = arg; + confComponents(dc, sc, *cmd->server); + return NULL; +} + +/** + * HTTP server module declaration. + */ +const command_rec commands[] = { + AP_INIT_TAKE1("TuscanyHome", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"), + AP_INIT_TAKE1("SCAWiringServerName", (const char*(*)())confWiringServerName, NULL, RSRC_CONF, "SCA wiring server name"), + 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, NULL, NULL, 0, NO_ARGS, NULL} +}; + +int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, unused server_rec *s) { + return OK; +} + +void childInit(apr_pool_t* p, server_rec* svr_rec) { + gc_scoped_pool pool(p); + ServerConf* c = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_eval); + if(c == NULL) { + cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; + exit(APEXIT_CHILDFATAL); + } +} + +void registerHooks(unused 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_eval = { + STANDARD20_MODULE_STUFF, + // dir config and merger + tuscany::httpd::makeDirConf<tuscany::server::modeval::DirConf>, NULL, + // server config and merger + tuscany::httpd::makeServerConf<tuscany::server::modeval::ServerConf>, NULL, + // commands and hooks + tuscany::server::modeval::commands, tuscany::server::modeval::registerHooks +}; + +} diff --git a/sca-cpp/trunk/modules/server/mod-scheme.hpp b/sca-cpp/trunk/modules/server/mod-scheme.hpp index d62578544f..5c6ea9ef7d 100644 --- a/sca-cpp/trunk/modules/server/mod-scheme.hpp +++ b/sca-cpp/trunk/modules/server/mod-scheme.hpp @@ -32,7 +32,6 @@ #include "function.hpp" #include "list.hpp" #include "value.hpp" -#include "debug.hpp" #include "monad.hpp" #include "../scheme/eval.hpp" #include "../http/httpd.hpp" diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index 6b4308edda..88a57659ef 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -31,7 +31,6 @@ #include "list.hpp" #include "tree.hpp" #include "value.hpp" -#include "debug.hpp" #include "monad.hpp" #include "../scdl/scdl.hpp" #include "../http/httpd.hpp" diff --git a/sca-cpp/trunk/modules/server/scheme-conf b/sca-cpp/trunk/modules/server/scheme-conf new file mode 100755 index 0000000000..18f3a885bc --- /dev/null +++ b/sca-cpp/trunk/modules/server/scheme-conf @@ -0,0 +1,26 @@ +#!/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 a scheme server conf +here=`readlink -f $0`; here=`dirname $here` +root=`readlink -f $1` + +cat >>$root/conf/httpd.conf <<EOF +LoadModule mod_tuscany_eval $here/.libs/libmod_tuscany_eval.so +EOF diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf index a55c04b7d8..ae175ee2f8 100755 --- a/sca-cpp/trunk/modules/server/server-conf +++ b/sca-cpp/trunk/modules/server/server-conf @@ -25,7 +25,5 @@ mkdir -p $root mkdir -p $root/logs mkdir -p $root/conf cat >>$root/conf/httpd.conf <<EOF -LoadModule mod_tuscany_eval $here/.libs/libmod_tuscany_eval.so LoadModule mod_tuscany_wiring $here/.libs/libmod_tuscany_wiring.so EOF - diff --git a/sca-cpp/trunk/modules/server/server-test b/sca-cpp/trunk/modules/server/server-test index 4c90711a30..97b3fd919b 100755 --- a/sca-cpp/trunk/modules/server/server-test +++ b/sca-cpp/trunk/modules/server/server-test @@ -20,6 +20,7 @@ # Setup ../http/httpd-conf tmp 8090 htdocs ./server-conf tmp +./scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> diff --git a/sca-cpp/trunk/modules/server/wiring-test b/sca-cpp/trunk/modules/server/wiring-test index 5b3a678f7f..29eef996e6 100755 --- a/sca-cpp/trunk/modules/server/wiring-test +++ b/sca-cpp/trunk/modules/server/wiring-test @@ -22,6 +22,7 @@ echo "Testing..." # Setup ../http/httpd-conf tmp 8090 htdocs ./server-conf tmp +./scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> diff --git a/sca-cpp/trunk/test/store-python/Makefile.am b/sca-cpp/trunk/test/store-python/Makefile.am index 345e58d544..2bdd776e10 100644 --- a/sca-cpp/trunk/test/store-python/Makefile.am +++ b/sca-cpp/trunk/test/store-python/Makefile.am @@ -15,5 +15,8 @@ # specific language governing permissions and limitations # under the License. +if WANT_PYTHON + TESTS = server-test +endif diff --git a/sca-cpp/trunk/test/store-python/server-test b/sca-cpp/trunk/test/store-python/server-test index b41c4e5393..aacf9e5a77 100755 --- a/sca-cpp/trunk/test/store-python/server-test +++ b/sca-cpp/trunk/test/store-python/server-test @@ -22,6 +22,7 @@ echo "Testing..." # Setup ../../modules/http/httpd-conf tmp 8090 htdocs ../../modules/server/server-conf tmp +../../modules/python/python-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> diff --git a/sca-cpp/trunk/test/store-scheme/Makefile.am b/sca-cpp/trunk/test/store-scheme/Makefile.am index 19b2640f3b..268e111805 100644 --- a/sca-cpp/trunk/test/store-scheme/Makefile.am +++ b/sca-cpp/trunk/test/store-scheme/Makefile.am @@ -17,10 +17,7 @@ noinst_PROGRAMS = script-test -INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${JS_INCLUDE} - script_test_SOURCES = script-test.cpp -script_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${JS_LIB} -lmozjs +script_test_LDADD = -lxml2 -lmozjs TESTS = script-test server-test - diff --git a/sca-cpp/trunk/test/store-scheme/server-test b/sca-cpp/trunk/test/store-scheme/server-test index b41c4e5393..bb327347a8 100755 --- a/sca-cpp/trunk/test/store-scheme/server-test +++ b/sca-cpp/trunk/test/store-scheme/server-test @@ -22,6 +22,7 @@ echo "Testing..." # Setup ../../modules/http/httpd-conf tmp 8090 htdocs ../../modules/server/server-conf tmp +../../modules/server/scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF <Location /> |