Copy trunk into gcc-4.4 branch before porting to gcc-4.5.

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@935127 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
jsdelfino 2010-04-17 05:00:18 +00:00
commit 5e5a4c9daa
380 changed files with 39773 additions and 0 deletions

View file

@ -0,0 +1,5 @@
Apache Tuscany SCA Runtime
==========================
The Apache Software Foundation (http://www.apache.org/)

View file

@ -0,0 +1,203 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed 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.

View file

@ -0,0 +1,12 @@
Apache Tuscany SCA Runtime
==========================
For a log of all changes see the Tuscany commits mailing list:
commits@tuscany.apache.org
Archives:
http://www.mail-archive.com/commits@tuscany.apache.org
To subscribe send an email to:
commits-subscribe@tuscany.apache.org

View file

@ -0,0 +1,284 @@
Apache Tuscany SCA Runtime
==========================
Automated installation from scratch on Ubuntu 9.10
==================================================
Tuscany provides an automated install script for Ubuntu 9.10. You can start
with a fresh Ubuntu Server 9.10 system, the ubuntu-install script takes care
of all the download, build and installation steps for you.
The required system tools and libraries are downloaded and installed using
apt-get. The Tuscany project and its dependencies (Apache HTTPD server, Apache
Axis2/C etc) are downloaded, built and installed in the current directory.
To run the automated installation:
mkdir tuscany
cd tuscany
wget http://svn.apache.org/repos/asf/tuscany/sca-cpp/trunk/ubuntu/ubuntu-install
chmod +x ./ubuntu-install
./ubuntu-install
The script will display each command as it's executed.
That's all you need to do to build and install the Tuscany SCA runtime on
Ubuntu 9.10.
For manual build and install steps on other systems or if you need to customize
your installation, read on...
Building
========
The Tuscany SCA Linux build uses the GNU Autotools tool chain.
First install the following development tools:
autoconf-2.64
automake-1.11
g++-4.4.1
libtool-2.2.6
doxygen-1.6.1
Install the following binaries:
curl-7-19-5
Then install the following development dependencies:
Apache HTTP server and APR:
httpd-2.2-15 (http://httpd.apache.org/)
with included libapr and libaprutil
built with OpenSSL libssl-0.9.8g
Memcached:
memcached-1.4.4 (http://memcached.org/)
built with libevent-1.4.11
XML:
libxml2-2.7.7 (http://xmlsoft.org/)
CURL:
libcurl4-openssl-7.19.5
JSON:
Mozilla TraceMonkey libmozjs (https://wiki.mozilla.org/JavaScript:TraceMonkey)
also included in xulrunner-1.9.1.8
Key/value store:
tinycdb-0.77 (http://www.corpit.ru/mjt/tinycdb.html)
Optional dependencies:
Web Services:
Apache Axis2/C 1.6.0 (http://ws.apache.org/axis2/c/)
Queueing:
Apache Qpid/C++ 0.6 (http://qpid.apache.org/)
built with libuuid-2.16, libboost-1.38.1, libboost-program-options-1.38.1 and
libboost-filesystem-1.38.1
Python:
Python 2.6.4 (http://www.python.org/)
Google AppEngine 1.3.2 (http://code.google.com/appengine/)
Java:
a Java 5+ JDK (http://openjdk.java.net/, http://harmony.apache.org/)
XMPP Chat:
Apache Vysper 0.5 (http://mina.apache.org/)
Libstrophe (http://code.stanziq.com/cgit/strophe/libstrophe/)
build it from source at git://code.stanziq.com//libstrophe
requires libcheck-0.9.6
SQL Database:
postgresql-9.0 (http://www.postgresql.org/)
To configure the Tuscany SCA build do this:
./bootstrap
./configure --prefix=<install dir>
To enable debugging and strict warning compile options, add:
--enable-maintainer-mode
To enable gprof profiling, add:
--enable-profiling
To enable multi-threading (required by the Queue and Chat components and
for running with the HTTPD worker or event multi-threaded MPMs):
--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 (requires Apache Axis2/C):
--enable-webservice
To build the Queue utility component (requires Apache Qpid/C++):
--enable-queue
To build the Chat utility component (requires Libstrophe and optionally Apache
Vysper if you want to run the tests with a local Vysper XMPP server):
--enable-chat
To build the SQL Database utility component (requires PostgreSQL):
--enable-sqldb
To generate doxygen documentation, add:
--enable-doxygen
To configure where to find dependencies, see the --with-* options described
in the configure help:
./configure --help
Here's an example configuration, tested on Ubuntu 9.10, with the system
dependencies installed in the standard system directories and some of the
dependencies installed under $HOME:
./configure --prefix=$HOME/tuscany-sca-cpp-bin \
--with-apr=$HOME/httpd-2.2.13-bin --with-httpd=$HOME/httpd-2.2.13-bin \
--with-memcached=$HOME/memcached-1.4.4-bin \
--with-tinycdb=$HOME/tinycdb-0.77-bin \
--with-curl=$HOME/curl-7.19.5-bin --with-libxml2=/usr \
--with-js-include=/usr/include/xulrunner-1.9.1.8/unstable \
--with-js-lib=/usr/lib/xulrunner-1.9.1.8 \
--enable-threads \
--enable-python --with-python=/usr \
--enable-gae --with-gae=$HOME/google_appengine \
--enable-java --with-java=/usr/lib/jvm/default-java \
--enable-webservice --with-axis2c=$HOME/axis2c-1.6.0-bin \
--with-libxml2=$HOME/libxml2-2.7.7-bin \
--enable-queue --with-qpidc=$HOME/qpidc-0.6-bin \
--enable-chat --with-libstrophe=$HOME/libstrophe-bin \
--with-vysper=$HOME/vysper-0.5 \
--enable-sqldb --with-pgsql=$HOME/postgresql-9.0-bin \
--enable-maintainer-mode
To build the Tuscany SCA runtime, do this:
make
To run the tests, do this:
make check
To build ctags for the source, do this:
make ctags
To build a source distribution, do this:
make dist
To build a binary distribution, do this:
make bindist
Installing
==========
To install the Tuscany SCA binaries, do this:
make install
Building dependencies from source
=================================
Here are example build and install steps for some of the dependencies.
Apache HTTPD, including APR, using the HTTP prefork MPM (recommended):
wget http://www.apache.org/dist/httpd/httpd-2.2.15.tar.gz
tar xzf httpd-2.2.15.tar.gz
cd httpd-2.2.15
./configure --enable-ssl --enable-proxy --enable-rewrite --with-included-apr \
--with-mpm=prefork --prefix=$HOME/httpd-2.2.15-bin
make
make install
export PATH=$HOME/httpd-2-2.15-bin/bin:$PATH
Memcached:
wget http://memcached.googlecode.com/files/memcached-1.4.4.tar.gz
tar xzf memcached-1.4.4.tar.gz
cd memcached-1.4.4
./configure --prefix=$HOME/memcached-1.4.4-bin
make
make install
TinyCDB:
wget http://www.corpit.ru/mjt/tinycdb/tinycdb_0.77.tar.gz
tar xzf tinycdb_0.77.tar.gz
cd tinycdb-0.77
make
make prefix=$HOME/tinycdb-0.77-bin install
CURL:
wget http://curl.haxx.se/download/curl-7.19.5.tar.gz
tar xzf curl-7.19.5.tar.gz
cd curl-7.19.5
./configure --prefix=$HOME/curl-7.19.5-bin
make
make install
Libxml2:
wget ftp://xmlsoft.org/libxml2/libxml2-sources-2.7.7.tar.gz
tar xzf libxml2-sources-2.7.7.tar.gz
cd libxml2-2.7.7
./configure --prefix=$HOME/libxml2-2.7.7-bin
make
make install
TraceMonkey:
wget http://hg.mozilla.org/tracemonkey/archive/e4364736e170.tar.gz
tar xzf tracemonkey-e4364736e170.tar.gz
cd tracemonkey-e4364736e170/js/src
autoconf2.13
./configure --prefix=$HOME/tracemonkey-bin
make
make install
Apache Axis2/C:
wget http://www.apache.org/dist/ws/axis2-c/1_6_0/axis2c-src-1.6.0.tar.gz
tar xzf axis2c-src-1.6.0.tar.gz
cd axis2c-src-1.6.0
./configure --enable-libxml2 --enable-openssl \
--with-apache2=$HOME/httpd-2.2.15-bin/include --prefix=$HOME/axis2c-1.6.0-bin
make
make install
export AXIS2C_HOME=$HOME/axis2c-1.6.0-bin
Apache Qpid/C++:
wget http://www.apache.org/dist/qpid/0.6/qpid-cpp-0.6.tar.gz
tar xzf qpid-cpp-0.6.tar.gz
cd qpidc-0.6
./configure --prefix=$HOME/qpidc-0.6-bin
make
make install
Libstrophe:
git clone git://code.stanziq.com/libstrophe
cd libstrophe
git submodule init
git submodule update
aclocal
automake --add-missing --foreign --copy
autoconf
./configure --prefix=$HOME/libstrophe-bin
make
make install
cd ..
mkdir -p libstrophe-bin/include
cp libstrophe/*.h libstrophe-bin/include
cp libstrophe/src/*.h libstrophe-bin/include
PostgreSQL:
wget http://wwwmaster.postgresql.org/download/mirrors-ftp/source/9.0alpha5/postgresql-9.0alpha5.tar.gz
tar xzf postgresql-9.0alpha5.tar.gz
cd postgresql-9.0alpha5
./configure --prefix=$HOME/postgresql-9.0-bin
make
make install

View file

@ -0,0 +1,323 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed 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.
================================================================================
Apache Tuscany SCA C++ Subcomponents:
The Tuscany SCA C++ release includes a number of subcomponents with separate
copyright notices and license terms. Your use of the source code for these
subcomponents is subject to the terms and conditions of the following licenses.
================================================================================
The xsd component includes XML files under the following license:
Copyright OASIS 2005, 2009. All Rights Reserved.
All capitalized terms in the following text have the meanings assigned to them in the OASIS Intellectual
Property Rights Policy (the "OASIS IPR Policy"). The full Policy may be found at the OASIS website.
This document and translations of it may be copied and furnished to others, and derivative works that
comment on or otherwise explain it or assist in its implementation may be prepared, copied, published,
and distributed, in whole or in part, without restriction of any kind, provided that the above copyright
notice and this section are included on all such copies and derivative works. However, this document
itself may not be modified in any way, including by removing the copyright notice or references to OASIS,
except as needed for the purpose of developing any document or deliverable produced by an OASIS
Technical Committee (in which case the rules applicable to copyrights, as set forth in the OASIS IPR
Policy, must be followed) or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors
or assigns.
This document and the information contained herein is provided on an "AS IS" basis and OASIS
DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP
RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE.
OASIS requests that any OASIS Party or any other party that believes it has patent claims that would
necessarily be infringed by implementations of this OASIS Committee Specification or OASIS Standard,
to notify OASIS TC Administrator and provide an indication of its willingness to grant patent licenses to
such patent claims in a manner consistent with the IPR Mode of the OASIS Technical Committee that
produced this specification.
OASIS invites any party to contact the OASIS TC Administrator if it is aware of a claim of ownership of
any patent claims that would necessarily be infringed by implementations of this specification by a patent
holder that is not willing to provide a license to such patent claims in a manner consistent with the IPR
Mode of the OASIS Technical Committee that produced this specification. OASIS may include such
claims on its website, but disclaims any obligation to do so.
OASIS takes no position regarding the validity or scope of any intellectual property or other rights that
might be claimed to pertain to the implementation or use of the technology described in this document or
the extent to which any license under such rights might or might not be available; neither does it represent
that it has made any effort to identify any such rights. Information on OASIS' procedures with respect to
rights in any document or deliverable produced by an OASIS Technical Committee can be found on the
OASIS website. Copies of claims of rights made available for publication and any assurances of licenses
to be made available, or the result of an attempt made to obtain a general license or permission for the use
of such proprietary rights by implementers or users of this OASIS Committee Specification or OASIS
Standard, can be obtained from the OASIS TC Administrator. OASIS makes no representation that any
information or list of intellectual property rights will at any time be complete, or that any claims in such list
are, in fact, Essential Claims.
The names "OASIS", are trademarks of OASIS, the owner and developer of this specification, and should
be used only to refer to the organization and its official outputs. OASIS welcomes reference to, and
implementation and use of, specifications, while reserving the right to enforce its marks against misleading
uses. Please see http://www.oasis-open.org/who/trademark.php for above guidance.
================================================================================
The xsd component includes XML files under the following license:
http://www.w3.org/Consortium/Legal/copyright-software-19980720
W3C® SOFTWARE NOTICE AND LICENSE
Copyright (c) 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche
en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/
This W3C work (including software, documents, or other related items) is being provided by the copyright holders under
the following license. By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood,
and will comply with the following terms and conditions:
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification,
for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies
of the software and documentation or portions thereof, including modifications, that you make:
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short
notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed
or derivative code: "Copyright (c) [$date-of-software] World Wide Web Consortium, (Massachusetts Institute of Technology,
Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs
to the location from which the code is derived.)
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE
OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE
OF THE SOFTWARE OR DOCUMENTATION.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software
without specific, written prior permission. Title to copyright in this software and any associated documentation will
at all times remain with copyright holders.
================================================================================
The components/chat component includes the Libstrophe library under the
following MIT license:
Copyright (c) 2005-2009 Collecta, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================================================

View file

@ -0,0 +1,45 @@
# 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.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = kernel modules components test doc samples
datadir=$(prefix)
data_DATA = INSTALL README LICENSE COPYING NOTICE
nobase_data_DATA = xsd/*.xsd xsd/external/*.xsd xsd/external/*.dtd
install-data-hook:
rm -rf $(prefix)/doc
cp -r doc $(prefix)
rm -f $(prefix)/doc/Makefile* $(prefix)/doc/Doxyfile*
rm -rf `find $(prefix)/doc -type d -name .svn`
rm -rf `find $(prefix)/doc -type d -name .deps`
rm -rf $(prefix)/test
dist-hook:
rm -rf `find $(distdir)/ -type d -name .svn`
rm -rf `find $(distdir)/ -type d -name .deps`
bindist: install
rm -rf ${PACKAGE}-${PACKAGE_VERSION}-bin
mkdir ${PACKAGE}-${PACKAGE_VERSION}-bin
cp -r $(prefix)/* ${PACKAGE}-${PACKAGE_VERSION}-bin
rm -rf ${PACKAGE}-${PACKAGE_VERSION}-bin/test
tar -cf - ${PACKAGE}-${PACKAGE_VERSION}-bin | gzip -c > ${PACKAGE}-${PACKAGE_VERSION}-bin.tar.gz
rm -rf ${PACKAGE}-${PACKAGE_VERSION}-bin

View file

@ -0,0 +1,13 @@
Apache Tuscany SCA Runtime
==========================
For any news see the Tuscany development mailing list:
dev@tuscany.apache.org
Archives:
http://www.mail-archive.com/dev@tuscany.apache.org
http://marc.info/?l=tuscany-dev
To subscribe send an email to:
dev-subscribe@tuscany.apache.org

View file

@ -0,0 +1,42 @@
Apache Tuscany SCA C++
Copyright 2005, 2010 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/)
This product includes software under the OASIS Specification License
with the following copyright:
Copyright(C) OASIS(R) 2005,2009. All Rights Reserved.
OASIS trademark, IPR and other policies apply.
This product includes software under the W3C(c) Software License
with the following copyright:
Copyright (c) 2008 World Wide Web Consortium, (Massachusetts Institute of Technology,
European Research Consortium for Informatics and Mathematics, Keio University).
All Rights Reserved. This work is distributed under the W3C(c) Software License [1] in
the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
This product includes software under the W3C(c) Software License
with the following copyright:
Copyright 2001 The Internet Society and W3C (Massachusetts Institute
of Technology, Institut National de Recherche en Informatique et en
Automatique, Keio University). All Rights Reserved.
http://www.w3.org/Consortium/Legal/
This document is governed by the W3C Software License [1] as described
in the FAQ [2].
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
This product includes software under the MIT license
with the following copyright:
Copyright (c) 2005-2009 Collecta, Inc.

View file

@ -0,0 +1,81 @@
Apache Tuscany SCA Runtime
==========================
Getting the source code
=======================
To checkout the source code with commit access, do this:
git svn init -s https://svn.apache.org/repos/asf/tuscany/sca-cpp tuscany-sca-cpp
cd tuscany-sca-cpp
wget -P .git http://git.apache.org/authors.txt
git config svn.authorsfile .git/authors.txt
git config user.email <you>@apache.org
git config svn.rmdir true
git svn fetch --log-window-size 10000
To checkout the source without commit access, do this:
git clone git://git.apache.org/tuscany-sca-cpp
or
svn checkout http://svn.apache.org/repos/asf/tuscany/sca-cpp tuscany-sca-cpp
Layout
======
Here's a rough guide to the Tuscany SCA source tree:
/
|-- trunk Master development branch
| |
| |-- kernel SCA runtime kernel
| |
| |-- modules Modules that plug into the runtime
| | |-- atom AtomPub encoding
| | |-- json JSON-RPC encoding
| | |-- http HTTP protocol
| | |-- java Support for Java components
| | |-- python Support for Python components
| | |-- scheme Support for Scheme components
| | |-- server Apache HTTPD server integration
| | |-- wsgi Python WSGI server integration
| |
| |-- components Useful SCA components
| | |-- cache Key/value memory cache
| | |-- chat XMPP chat
| | |-- log Logger
| | |-- queue AMQP message queue
| | |-- sqldb SQL database
| | |-- store Key/value persistent store
| | |-- webservice Web service gateway
| |
| |-- test Integration tests
| |
| |-- samples Sample Applications
| |
| |-- ubuntu Automated install on Ubuntu 9.10
|
|-- branches Topic and release branches
|
|-- tags Release tags
Building
========
See the INSTALL file.
Contributing to the project
===========================
To contribute to the project or report issues see the Tuscany development
mailing list:
dev@tuscany.apache.org
Archives:
http://www.mail-archive.com/dev@tuscany.apache.org
http://marc.info/?l=tuscany-dev
To subscribe send an email to:
dev-subscribe@tuscany.apache.org

View file

@ -0,0 +1,31 @@
#!/bin/bash
# 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.
for i in "libtoolize --force" aclocal autoconf autoheader
do
echo -n "Running $i..."
$i || exit 1
echo 'done.'
done
echo -n 'Running automake...'
automake --add-missing
echo 'done.'
exit 0

View file

@ -0,0 +1,22 @@
# 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.
SUBDIRS = cache chat log queue sqldb store webservice
includedir = $(prefix)/include/components
nobase_include_HEADERS = */*.hpp

View file

@ -0,0 +1,35 @@
# 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.
comp_SCRIPTS = memcached-start memcached-stop
compdir=$(prefix)/components/cache
comp_DATA = memcached.prefix
memcached.prefix: $(top_builddir)/config.status
echo ${MEMCACHED_PREFIX} >memcached.prefix
comp_LTLIBRARIES = libmemcache.la
libmemcache_la_SOURCES = memcache.cpp
memcache_test_SOURCES = memcache-test.cpp
memcache_test_LDFLAGS = -lxml2
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
noinst_PROGRAMS = memcache-test client-test
TESTS = memcached-test server-test

View file

@ -0,0 +1,130 @@
/*
* 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 cache component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/curl.hpp"
namespace tuscany {
namespace cache {
const string uri("http://localhost:8090/memcache");
bool testCache() {
http::CURLSession cs;
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);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == a);
}
const list<value> j = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55"));
const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == b);
}
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(!hasContent(val));
}
return true;
}
struct getLoop {
const string path;
const value entry;
http::CURLSession cs;
getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
}
const bool operator()() const {
const failable<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs;
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
cout << "Cache get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::cache::testCache();
tuscany::cache::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,82 @@
/*
* 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 Memcached access functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "memcache.hpp"
namespace tuscany {
namespace memcache {
bool testMemCached() {
MemCached ch("127.0.0.1", 11211);
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), ch)));
assert((get(k, ch)) == value(string("AAA")));
assert(hasContent(put(k, string("aaa"), ch)));
assert((get(k, ch)) == value(string("aaa")));
assert(hasContent(del(k, ch)));
assert(!hasContent(get(k, ch)));
return true;
}
struct getLoop {
const value k;
MemCached& ch;
getLoop(const value& k, MemCached& ch) : k(k), ch(ch) {
}
const bool operator()() const {
assert((get(k, ch)) == value(string("CCC")));
return true;
}
};
bool testGetPerf() {
const value k = mklist<value>("c");
MemCached ch("127.0.0.1", 11211);
assert(hasContent(post(k, string("CCC"), ch)));
const lambda<bool()> gl = getLoop(k, ch);
cout << "Memcached get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::memcache::testMemCached();
tuscany::memcache::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="memcache">
<component name="memcache">
<implementation.cpp path=".libs" library="libmemcache"/>
<service name="memcache">
<t:binding.http uri="memcache"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,133 @@
/*
* 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$ */
/**
* Memcached-based cache component implementation.
*/
#include <apr_uuid.h>
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "memcache.hpp"
namespace tuscany {
namespace cache {
/**
* Get an item from the cache.
*/
const failable<value> get(const list<value>& params, memcache::MemCached& ch) {
return memcache::get(car(params), ch);
}
/**
* Post an item to the cache.
*/
const value uuidValue() {
apr_uuid_t uuid;
apr_uuid_get(&uuid);
char buf[APR_UUID_FORMATTED_LENGTH];
apr_uuid_format(buf, &uuid);
return value(string(buf, APR_UUID_FORMATTED_LENGTH));
}
const failable<value> post(const list<value>& params, memcache::MemCached& ch) {
const value id = append<value>(car(params), mklist(uuidValue()));
const failable<bool> val = memcache::post(id, cadr(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return id;
}
/**
* Put an item into the cache.
*/
const failable<value> put(const list<value>& params, memcache::MemCached& ch) {
const failable<bool> val = memcache::put(car(params), cadr(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Delete an item from the cache.
*/
const failable<value> del(const list<value>& params, memcache::MemCached& ch) {
const failable<bool> val = memcache::del(car(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Component implementation lambda function.
*/
class applyCache {
public:
applyCache(memcache::MemCached& ch) : ch(ch) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "get")
return get(cdr(params), ch);
if (func == "post")
return post(cdr(params), ch);
if (func == "put")
return put(cdr(params), ch);
if (func == "delete")
return del(cdr(params), ch);
return tuscany::mkfailure<tuscany::value>();
}
private:
memcache::MemCached& ch;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to memcached
memcache::MemCached& ch = *(new (gc_new<memcache::MemCached>()) memcache::MemCached("127.0.0.1", 11211));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyCache(ch)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::cache::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,175 @@
/*
* 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$ */
#ifndef tuscany_memcache_hpp
#define tuscany_memcache_hpp
/**
* Memcached access functions.
*/
#include "apr.h"
#include "apu.h"
#include "apr_general.h"
#include "apr_strings.h"
#include "apr_hash.h"
#include "apr_memcache.h"
#include "apr_network_io.h"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace memcache {
/**
* Represents a memcached context.
*/
class MemCached {
public:
MemCached() : owner(false) {
}
MemCached(const string host, const int port) : owner(true) {
apr_pool_create(&pool, NULL);
apr_memcache_create(pool, 1, 0, &mc);
init(host, port);
}
MemCached(const MemCached& c) : owner(false) {
pool = c.pool;
mc = c.mc;
}
~MemCached() {
if (!owner)
return;
apr_pool_destroy(pool);
}
private:
bool owner;
apr_pool_t* pool;
apr_memcache_t* mc;
friend const failable<bool> post(const value& key, const value& val, const MemCached& cache);
friend const failable<bool> put(const value& key, const value& val, const MemCached& cache);
friend const failable<value> get(const value& key, const MemCached& cache);
friend const failable<bool> del(const value& key, const MemCached& cache);
/**
* Initialize the memcached context.
*/
const failable<bool> init(const string& host, const int port) {
apr_memcache_server_t *server;
const apr_status_t sc = apr_memcache_server_create(pool, c_str(host), (apr_port_t)port, 0, 1, 1, 60, &server);
if (sc != APR_SUCCESS)
return mkfailure<bool>("Could not create server");
const apr_status_t as = apr_memcache_add_server(mc, server);
if (as != APR_SUCCESS)
return mkfailure<bool>("Could not add server");
return true;
}
};
/**
* Post a new item to the cache.
*/
const failable<bool> post(const value& key, const value& val, const MemCached& cache) {
debug(key, "memcache::post::key");
debug(val, "memcache::post::value");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const apr_status_t rc = apr_memcache_add(cache.mc, c_str(ks), const_cast<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not add entry");
debug(true, "memcache::post::result");
return true;
}
/**
* Update an item in the cache. If the item doesn't exist it is added.
*/
const failable<bool> put(const value& key, const value& val, const MemCached& cache) {
debug(key, "memcache::put::key");
debug(val, "memcache::put::value");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const apr_status_t rc = apr_memcache_set(cache.mc, c_str(ks), const_cast<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not set entry");
debug(true, "memcache::put::result");
return true;
}
/**
* Get an item from the cache.
*/
const failable<value> get(const value& key, const MemCached& cache) {
debug(key, "memcache::get::key");
const string ks(scheme::writeValue(key));
apr_pool_t* vpool;
const apr_status_t pc = apr_pool_create(&vpool, cache.pool);
if (pc != APR_SUCCESS)
return mkfailure<value>("Could not allocate memory");
char *data;
apr_size_t size;
const apr_status_t rc = apr_memcache_getp(cache.mc, cache.pool, c_str(ks), &data, &size, NULL);
if (rc != APR_SUCCESS) {
apr_pool_destroy(vpool);
return mkfailure<value>("Could not get entry");
}
const value val(scheme::readValue(string(data, size)));
apr_pool_destroy(vpool);
debug(val, "memcache::get::result");
return val;
}
/**
* Delete an item from the cache
*/
const failable<bool> del(const value& key, const MemCached& cache) {
debug(key, "memcache::delete::key");
const string ks(scheme::writeValue(key));
const apr_status_t rc = apr_memcache_delete(cache.mc, c_str(ks), 0);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not delete entry");
debug(true, "memcache::delete::result");
return true;
}
}
}
#endif /* tuscany_memcache_hpp */

View file

@ -0,0 +1,25 @@
#!/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.
# Start memcached
here=`readlink -f $0`; here=`dirname $here`
memcached_prefix=`cat $here/memcached.prefix`
$memcached_prefix/bin/memcached -d -l 127.0.0.1 -m 4 -p 11211

View file

@ -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.
# Stop memcached
here=`readlink -f $0`; here=`dirname $here`
memcached_prefix=`cat $here/memcached.prefix`
mc="$memcached_prefix/bin/memcached -d -l 127.0.0.1 -m 4 -p 11211"
kill `ps -ef | grep -v grep | grep "${mc}" | awk '{ print $2 }'`

View file

@ -0,0 +1,30 @@
#!/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
./memcached-start
sleep 1
# Test
./memcache-test 2>/dev/null
rc=$?
# Cleanup
./memcached-stop
return $rc

View file

@ -0,0 +1,41 @@
#!/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
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite memcache.composite
EOF
./memcached-start
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
./memcached-stop
sleep 2
return $rc

View file

@ -0,0 +1,54 @@
# 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.
JAVAROOT = $(top_builddir)/components/chat
if WANT_CHAT
INCLUDES = -I${LIBSTROPHE_INCLUDE}
comp_SCRIPTS = vysper-start vysper-stop vysper-classpath
compdir=$(prefix)/components/chat
comp_DATA = vysper.prefix
vysper.prefix: $(top_builddir)/config.status
echo ${VYSPER_PREFIX} >vysper.prefix
comp_LTLIBRARIES = libchatter.la
libchatter_la_SOURCES = chatter.cpp
libchatter_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
xmpp_test_SOURCES = xmpp-test.cpp
xmpp_test_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
noinst_PROGRAMS = xmpp-test client-test
if WANT_VYSPER
AM_JAVACFLAGS = -cp `${top_builddir}/components/chat/vysper-classpath ${VYSPER_PREFIX}`${JAVAROOT}
noinst_JAVA = test/*.java
CLEANFILES = test/*.class
TESTS = echo-test
endif
endif

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="chat">
<component name="print-sender">
<implementation.cpp path=".libs" library="libchatter"/>
<property name="jid">sca1@localhost</property>
<property name="password">sca1</property>
<service name="print-sender">
<t:binding.http uri="print-sender"/>
</service>
</component>
<component name="print-chatter">
<implementation.cpp path=".libs" library="libchatter"/>
<property name="jid">sca2@localhost</property>
<property name="password">sca2</property>
<service name="print-chatter">
<t:binding.http uri="print-chatter"/>
</service>
<reference name="relay" target="print"/>
</component>
<component name="print">
<t:implementation.scheme script="server-test.scm"/>
<service name="print">
<t:binding.http uri="print"/>
</service>
<reference name="report" target="print-chatter"/>
</component>
</composite>

View file

@ -0,0 +1,162 @@
/*
* 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$ */
/**
* XMPP chatter component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "parallel.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
/**
* Post an item to an XMPP JID.
*/
const failable<value> post(const list<value>& params, XMPPClient& xc) {
const value to = car<value>(car(params));
const value val = cadr(params);
debug(to, "chat::post::jid");
debug(val, "chat::post::value");
const failable<bool> r = post(to, val, xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
return value(mklist<value>(to));
}
/**
* A relay function that posts the XMPP messages it receives to a relay component reference.
*/
class relay {
public:
relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
}
const failable<bool> operator()(const value& jid, const value& val, unused XMPPClient& xc) const {
if (isNil(rel))
return true;
debug(jid, "chat::relay::jid");
debug(val, "chat::relay::value");
const value res = rel(mklist<value>("post", mklist<value>(jid), val));
return true;
}
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an XMPP session.
*/
class subscribe {
public:
subscribe(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& l, XMPPClient& xc) : l(l), xc(xc) {
}
const failable<bool> operator()() const {
gc_pool pool;
debug("chat::subscribe::listen");
const failable<bool> r = listen(l, const_cast<XMPPClient&>(xc));
debug("chat::subscribe::stopped");
return r;
}
private:
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l;
XMPPClient xc;
};
/**
* Chatter component lambda function
*/
class chatter {
public:
chatter(XMPPClient& xc, worker& w) : xc(xc), w(w) {
}
const value operator()(const list<value>& params) const {
const tuscany::value func(car(params));
if (func == "post")
return post(cdr(params), const_cast<XMPPClient&>(xc));
// Stop the chatter component
if (func != "stop")
return tuscany::mkfailure<tuscany::value>();
debug("chat::chatter::stop");
// Disconnect and shutdown the worker thread
disconnect(const_cast<XMPPClient&>(xc));
cancel(const_cast<worker&>(w));
debug("chat::chatter::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const XMPPClient xc;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the relay reference and the XMPP JID and password
const bool hasRelay = !isNil(cddr(params));
const value rel = hasRelay? car(params) : value(lambda<value(const list<value>&)>());
const list<value> props = hasRelay? cdr(params) : params;
const value jid = ((lambda<value(list<value>)>)car(props))(list<value>());
const value pass = ((lambda<value(list<value>)>)cadr(props))(list<value>());
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
// Listen and relay messages in a worker thread
worker w(3);
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(rl, xc)));
// Return the chatter component lambda function
return value(lambda<value(const list<value>&)>(chatter(xc, w)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::chat::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,111 @@
/*
* 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 chat component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "parallel.hpp"
#include "../../modules/http/curl.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
const value jid1("sca1@localhost");
const value pass1("sca1");
const value jid2("sca2@localhost");
const value pass2("sca2");
const value jid3("sca3@localhost");
const value pass3("sca3");
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
worker w(2);
bool received;
const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
assert(contains(from, "sca2@localhost"));
assert(val == entry);
received = true;
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
listen(l, xc);
return true;
}
};
bool testListen() {
received = false;
XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid3, pass3));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
submit(w, subs);
return true;
}
bool testPost() {
gc_scoped_pool pool;
http::CURLSession ch;
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch);
assert(hasContent(id));
return true;
}
bool testReceived() {
shutdown(w);
assert(received == true);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::chat::testListen();
tuscany::chat::testPost();
tuscany::chat::testReceived();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./vysper-start
sleep 3
# Test
./xmpp-test 2>/dev/null
rc=$?
# Cleanup
./vysper-stop
sleep 1
return $rc

View file

@ -0,0 +1,39 @@
#!/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
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite chat.composite
EOF
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 1
return $rc

View file

@ -0,0 +1,20 @@
; 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.
; Chat test case
(define (post key val report) (report "post" '("sca3@localhost") val))

View file

@ -0,0 +1,79 @@
/*
* 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.
*/
package test;
/**
* A test XMPP server, using Apache Vysper.
*/
import static java.lang.System.*;
import java.io.File;
import org.apache.vysper.mina.TCPEndpoint;
import org.apache.vysper.stanzasession.StanzaSessionFactory;
import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry;
import org.apache.vysper.xmpp.authorization.AccountManagement;
import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataModule;
import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempModule;
import org.apache.vysper.xmpp.modules.extension.xep0092_software_version.SoftwareVersionModule;
import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
import org.apache.vysper.xmpp.modules.extension.xep0202_entity_time.EntityTimeModule;
import org.apache.vysper.xmpp.server.XMPPServer;
class TestVysperServer {
public static void main(final String args[]) throws Exception {
out.println("Starting test Vysper server...");
// Add the XMPP users used by the xmpp-test and server-test test cases
// If you're using your own XMPP server you need to add these users manually
final StorageProviderRegistry providerRegistry = new MemoryStorageProviderRegistry();
final AccountManagement accountManagement = (AccountManagement)providerRegistry.retrieve(AccountManagement.class);
accountManagement.addUser("sca1@localhost", "sca1");
accountManagement.addUser("sca2@localhost", "sca2");
accountManagement.addUser("sca3@localhost", "sca3");
// Create and start XMPP server for domain: localhost
final XMPPServer server = new org.apache.vysper.xmpp.server.XMPPServer("localhost");
server.addEndpoint(new TCPEndpoint());
server.addEndpoint(new StanzaSessionFactory());
server.setStorageProviderRegistry(providerRegistry);
final File cert = new File(TestVysperServer.class.getClassLoader().getResource("bogus_mina_tls.cert").getPath());
server.setTLSCertificateInfo(cert, "boguspw");
server.start();
server.addModule(new SoftwareVersionModule());
server.addModule(new EntityTimeModule());
server.addModule(new VcardTempModule());
server.addModule(new XmppPingModule());
server.addModule(new PrivateDataModule());
out.println("Test Vysper server started...");
// Wait forever
final Object lock = new Object();
synchronized(lock) {
lock.wait();
}
System.out.println("Stopping test Vysper server...");
server.stop();
out.println("Test Vysper server stopped.");
System.exit(0);
}
}

View file

@ -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.
# Compute a classpath for running a Vysper server
here=`readlink -f $0`; here=`dirname $here`
if [ "$1" = "" ]; then
vysper_prefix=`cat $here/vysper.prefix`
else
vysper_prefix=$1
fi
jars=`find $vysper_prefix/lib -name "*.jar" | awk '{ printf "%s:", $1 }'`
echo "$vysper_prefix/config:$jars"

View file

@ -0,0 +1,25 @@
#!/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.
# Start Vysper test XMPP server
here=`readlink -f $0`; here=`dirname $here`
java_prefix=`cat $here/../../modules/java/java.prefix`
mkdir -p $here/tmp/logs
${java_prefix}/jre/bin/java -cp `$here/vysper-classpath`$here test.TestVysperServer 2>&1 1>>$here/tmp/logs/vysper.log &

View file

@ -0,0 +1,25 @@
#!/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.
# Stop Vysper test XMPP server
here=`readlink -f $0`; here=`dirname $here`
java_prefix=`cat $here/../../modules/java/java.prefix`
kill `ps -ef | grep -v grep | grep "${java_prefix}/jre/bin/java" | grep "vysper" | awk '{ print $2 }'`

View file

@ -0,0 +1,103 @@
/*
* 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 XMPP support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "parallel.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
const value jid1("sca1@localhost");
const value pass1("sca1");
const value jid2("sca2@localhost");
const value pass2("sca2");
worker w(2);
bool received;
const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
assert(contains(from, "sca1@localhost"));
assert(val == "hey");
received = true;
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
listen(l, xc);
return true;
}
};
bool testListen() {
received = false;
XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid2, pass2));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
submit(w, subs);
return true;
}
bool testPost() {
XMPPClient xc(jid1, pass1);
const failable<bool> c = connect(xc);
assert(hasContent(c));
const failable<bool> p = post(jid2, "hey", xc);
assert(hasContent(p));
return true;
}
bool testReceived() {
shutdown(w);
assert(received == true);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::chat::testListen();
tuscany::chat::testPost();
tuscany::chat::testReceived();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,330 @@
/*
* 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$ */
#ifndef tuscany_queue_hpp
#define tuscany_queue_hpp
/**
* XMPP support functions.
*/
#include <apr_uuid.h>
#include "strophe.h"
extern "C" {
#include "common.h"
}
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace chat {
/**
* XMPP runtime, one per process.
*/
class XMPPRuntime {
public:
XMPPRuntime() {
xmpp_initialize();
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
}
~XMPPRuntime() {
xmpp_shutdown();
}
private:
friend class XMPPClient;
xmpp_log_t* log;
} xmppRuntime;
/**
* Represents an XMPP client.
*/
const string resourceUUID() {
apr_uuid_t uuid;
apr_uuid_get(&uuid);
char buf[APR_UUID_FORMATTED_LENGTH];
apr_uuid_format(buf, &uuid);
return string(buf, APR_UUID_FORMATTED_LENGTH);
}
class XMPPClient {
public:
XMPPClient(const string& jid, const string& pass, bool owner = true) : owner(owner), ctx(xmpp_ctx_new(NULL, xmppRuntime.log)), conn(xmpp_conn_new(ctx)), connecting(false), connected(false), disconnecting(false) {
xmpp_conn_set_jid(conn, c_str(jid + "/" + resourceUUID()));
xmpp_conn_set_pass(conn, c_str(pass));
}
XMPPClient(const XMPPClient& xc) : owner(false), ctx(xc.ctx), conn(xc.conn), listener(xc.listener), connecting(xc.connecting), connected(xc.connected), disconnecting(xc.disconnecting) {
}
~XMPPClient() {
extern const failable<bool> disconnect(XMPPClient& xc);
if (!owner)
return;
if (!disconnecting)
disconnect(*this);
xmpp_conn_release(conn);
xmpp_ctx_free(ctx);
}
private:
friend int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
friend void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, const int err, xmpp_stream_error_t* const errstream, void *const udata);
friend int messageHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
friend const failable<bool> connect(XMPPClient& xc);
friend const failable<int> send(const char* data, const int len, XMPPClient& xc);
friend const failable<int> send(xmpp_stanza_t* const stanza, XMPPClient& xc);
friend const failable<bool> post(const value& to, const value& val, XMPPClient& xc);
friend const failable<bool> disconnect(XMPPClient& xc);
friend const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc);
const bool owner;
xmpp_ctx_t* ctx;
xmpp_conn_t* conn;
lambda<failable<bool>(const value&, const value&, XMPPClient&)> listener;
bool connecting;
bool connected;
bool disconnecting;
};
/**
* Make a text stanza.
*/
xmpp_stanza_t* textStanza(const char* text, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(stanza, text);
return stanza;
}
/**
* Make a named stanza.
*/
xmpp_stanza_t* namedStanza(const char* ns, const char* name, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(stanza, name);
if (ns != NULL)
xmpp_stanza_set_ns(stanza, ns);
return stanza;
}
/**
* Make a named stanza using a qualified name.
*/
xmpp_stanza_t* namedStanza(const char* name, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(stanza, name);
return stanza;
}
/**
* XMPP version handler.
*/
int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
XMPPClient& xc = *(XMPPClient*)udata;
// Build version reply stanza
xmpp_stanza_t* reply = namedStanza("iq", xc.ctx);
xmpp_stanza_set_type(reply, "result");
xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza));
xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from"));
xmpp_stanza_t* query = namedStanza(xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)), "query", xc.ctx);
xmpp_stanza_add_child(reply, query);
xmpp_stanza_t* name = namedStanza("name", xc.ctx);
xmpp_stanza_add_child(query, name);
xmpp_stanza_add_child(name, textStanza("Apache Tuscany", xc.ctx));
xmpp_stanza_t* version = namedStanza("version", xc.ctx);
xmpp_stanza_add_child(query, version);
xmpp_stanza_add_child(version, textStanza("1.0", xc.ctx));
// Send it
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
return 1;
}
/**
* XMPP message handler
*/
int messageHandler(unused xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
// Ignore noise
if(xmpp_stanza_get_child_by_name(stanza, "body") == NULL)
return 1;
if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error"))
return 1;
// Call the client listener function
XMPPClient& xc = *(XMPPClient*)udata;
const char* from = xmpp_stanza_get_attribute(stanza, "from");
const char* text = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));
if (isNil(xc.listener))
return 1;
const value val(scheme::readValue(text));
debug(from, "chat::messageHandler::from");
debug(val, "chat::messageHandler::body");
const failable<bool> r = xc.listener(value(string(from)), val, xc);
if (!hasContent(r) || !content(r)) {
// Stop listening
xc.listener = lambda<failable<bool>(const value&, const value&, XMPPClient&)>();
return 0;
}
return 1;
}
/**
* XMPP connection handler.
*/
void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, unused const int err, unused xmpp_stream_error_t* const errstream, void *const udata) {
XMPPClient& xc = *(XMPPClient*)udata;
xc.connecting = false;
if (status == XMPP_CONN_CONNECT) {
debug("chat::connHandler::connected");
xmpp_handler_add(conn, versionHandler, "jabber:iq:version", "iq", NULL, &xc);
// Send a <presence/> stanza so that we appear online to contacts
xmpp_stanza_t* pres = xmpp_stanza_new(xc.ctx);
xmpp_stanza_set_name(pres, "presence");
xmpp_send(conn, pres);
xmpp_stanza_release(pres);
xc.connected = true;
return;
}
debug("chat::connHandler::disconnected");
xc.connected = false;
if (xc.ctx->loop_status == XMPP_LOOP_RUNNING)
xc.ctx->loop_status = XMPP_LOOP_QUIT;
}
/**
* Connect to an XMPP server.
*/
const failable<bool> connect(XMPPClient& xc) {
xc.connecting = true;
xmpp_connect_client(xc.conn, NULL, 0, connHandler, &xc);
while(xc.connecting)
xmpp_run_once(xc.ctx, 20L);
if (!xc.connected)
return mkfailure<bool>("Couldn't connect to XMPP server");
return true;
}
/**
* Send a buffer on an XMPP session.
*/
const failable<int> send(const char* data, const int len, XMPPClient& xc) {
if (len == 0)
return 0;
const int written = xc.conn->tls? tls_write(xc.conn->tls, data, len) : sock_write(xc.conn->sock, data, len);
if (written < 0) {
xc.conn->error = xc.conn->tls? tls_error(xc.conn->tls) : sock_error();
return mkfailure<int>("Couldn't send stanza to XMPP server");
}
return send(data + written, len - written, xc);
}
/**
* Send a string on an XMPP session.
*/
const failable<int> send(const string& data, XMPPClient& xc) {
return send(c_str(data), length(data), xc);
}
/**
* Send a stanza on an XMPP session.
*/
const failable<int> send(xmpp_stanza_t* const stanza, XMPPClient& xc) {
char *buf;
size_t len;
const int rc = xmpp_stanza_to_text(stanza, &buf, &len);
if (rc != 0)
return mkfailure<int>("Couldn't convert stanza to text");
const failable<int> r = send(buf, len, xc);
if (!hasContent(r)) {
xmpp_free(xc.conn->ctx, buf);
return r;
}
xmpp_debug(xc.conn->ctx, "conn", "SENT: %s", buf);
xmpp_free(xc.conn->ctx, buf);
return content(r);
}
/**
* Post a message to an XMPP jid.
*/
const failable<bool> post(const value& to, const value& val, XMPPClient& xc) {
debug(to, "chat::post::to");
debug(val, "chat::post::body");
// Convert the value to a string
const string vs(scheme::writeValue(val));
// Build message stanza
xmpp_stanza_t* stanza = namedStanza("message", xc.ctx);
xmpp_stanza_set_type(stanza, "chat");
xmpp_stanza_set_attribute(stanza, "to", c_str(string(to)));
xmpp_stanza_t* body = namedStanza("body", xc.ctx);
xmpp_stanza_add_child(stanza, body);
xmpp_stanza_add_child(body, textStanza(c_str(vs), xc.ctx));
// Send it
const failable<int> r = send(stanza, xc);
xmpp_stanza_release(stanza);
if (!hasContent(r))
return mkfailure<bool>(reason(r));
return true;
}
/**
* Disconnect an XMPP session.
*/
const failable<bool> disconnect(XMPPClient& xc) {
xc.disconnecting = true;
const failable<int> r = send("</stream:stream>", xc);
if (!hasContent(r))
return mkfailure<bool>(reason(r));
return true;
}
/**
* Listen to messages received by an XMPP client.
*/
const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) {
debug("chat::listen");
xc.listener = listener;
xmpp_handler_add(xc.conn, messageHandler, NULL, "message", NULL, &xc);
xc.ctx->loop_status = XMPP_LOOP_RUNNING;
while(xc.connected && !isNil(xc.listener) && xc.ctx->loop_status == XMPP_LOOP_RUNNING)
xmpp_run_once(xc.ctx, 1000L);
return true;
}
}
}
#endif /* tuscany_xmpp_hpp */

View file

@ -0,0 +1,17 @@
# 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.

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="log">
<component name="log">
<implementation.cpp path=".libs" library="liblog"/>
<property name="file">sample.log</property>property>
<service name="log">
<t:binding.http uri="log"/>
</service>
</component>
</composite>

View file

@ -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.
if WANT_QUEUE
INCLUDES = -I${QPIDC_INCLUDE}
comp_SCRIPTS = qpidd-start qpidd-stop
compdir=$(prefix)/components/queue
comp_DATA = qpidc.prefix
qpidc.prefix: $(top_builddir)/config.status
echo ${QPIDC_PREFIX} >qpidc.prefix
comp_LTLIBRARIES = libqueue-sender.la libqueue-listener.la
libqueue_sender_la_SOURCES = queue-sender.cpp
libqueue_sender_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
libqueue_listener_la_SOURCES = queue-listener.cpp
libqueue_listener_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
qpid_test_SOURCES = qpid-test.cpp
qpid_test_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
noinst_PROGRAMS = qpid-test client-test
TESTS = send-test server-test
endif

View file

@ -0,0 +1,99 @@
/*
* 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 queue component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/curl.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
const value key(mklist<value>(string("report")));
const string qname("reportq");
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
bool testDeclareQueue() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = declareQueue(key, qname, qs);
assert(hasContent(r));
return true;
}
const bool listener(const value& k, const value& v) {
cerr << "k " << k << " v " << v << endl;
assert(k == key);
assert(v == entry);
return false;
}
bool testListen() {
QpidConnection qc;
QpidSession qs(qc);
QpidSubscription qsub(qs);
const lambda<bool(const value&, const value&)> l(listener);
listen(qname, l, qsub);
return true;
}
bool testPost() {
gc_scoped_pool pool;
http::CURLSession ch;
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender", ch);
assert(hasContent(id));
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::queue::testDeclareQueue();
tuscany::queue::testPost();
tuscany::queue::testListen();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,97 @@
/*
* 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 Qpid support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
const value key(mklist<value>("test"));
const string qname("testq");
bool testDeclareQueue() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = declareQueue(key, qname, qs);
assert(hasContent(r));
return true;
}
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
bool testPost() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = post(key, entry, qs);
assert(hasContent(r));
return true;
}
const bool listener(const value& k, const value& v) {
assert(k == key);
assert(v == entry);
return false;
}
bool testListen() {
QpidConnection qc;
QpidSession qs(qc);
QpidSubscription qsub(qs);
const lambda<bool(const value&, const value&)> l(listener);
listen(qname, l, qsub);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::queue::testDeclareQueue();
tuscany::queue::testPost();
tuscany::queue::testListen();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,260 @@
/*
* 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$ */
#ifndef tuscany_qpid_hpp
#define tuscany_qpid_hpp
/**
* AMQP queue access functions.
*/
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
#include <qpid/client/Connection.h>
#include <qpid/client/Session.h>
#include <qpid/client/MessageListener.h>
#include <qpid/client/SubscriptionManager.h>
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace queue {
/**
* Represents a Qpid connection.
*/
class QpidConnection {
public:
QpidConnection() : owner(true) {
c.open("localhost", 5672);
}
QpidConnection(const bool owner) : owner(owner) {
c.open("localhost", 5672);
}
QpidConnection(const QpidConnection& qc) : owner(false), c(qc.c) {
}
~QpidConnection() {
if (!owner)
return;
c.close();
}
private:
friend const failable<bool> close(QpidConnection& qc);
friend class QpidSession;
const bool owner;
qpid::client::Connection c;
};
/**
* Close a Qpid connection.
*/
const failable<bool> close(QpidConnection& qc) {
qc.c.close();
return true;
}
/**
* Represents a Qpid session.
*/
class QpidSession {
public:
QpidSession(QpidConnection& qc) : owner(true), s(qc.c.newSession()) {
}
QpidSession(QpidConnection& qc, const bool owner) : owner(owner), s(qc.c.newSession()) {
}
QpidSession(const QpidSession& qs) : owner(false), s(qs.s) {
}
~QpidSession() {
if (!owner)
return;
s.close();
}
private:
friend const failable<bool> close(QpidSession& qs);
friend const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs);
friend const failable<bool> post(const value& key, const value& val, QpidSession& qs);
friend class QpidSubscription;
const bool owner;
qpid::client::Session s;
};
/**
* Close a Qpid session.
*/
const failable<bool> close(QpidSession& qs) {
try {
qs.s.close();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Declare a key / AMQP queue pair.
*/
const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs) {
const string ks(scheme::writeValue(key));
try {
qs.s.queueDeclare(qpid::client::arg::queue=c_str(name));
qs.s.exchangeBind(qpid::client::arg::exchange="amq.direct", qpid::client::arg::queue=c_str(name), qpid::client::arg::bindingKey=c_str(ks));
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Post a key / value pair message to an AMQP broker.
*/
const failable<bool> post(const value& key, const value& val, QpidSession& qs) {
// Send in a message with the given key.
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
try {
qpid::client::Message message;
message.getDeliveryProperties().setRoutingKey(c_str(ks));
message.setData(c_str(vs));
qs.s.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="amq.direct");
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Represents a Qpid subscription.
*/
class QpidSubscription {
public:
QpidSubscription(QpidSession& qs) : owner(true), subs(qs.s) {
}
QpidSubscription(QpidSession& qs, const bool owner) : owner(owner), subs(qs.s) {
}
QpidSubscription(const QpidSubscription& qsub) : owner(false), subs(qsub.subs) {
}
~QpidSubscription() {
if (!owner)
return;
try {
subs.stop();
} catch (const qpid::Exception& e) {
mkfailure<bool>(string("Qpid failure: ") + e.what());
}
}
private:
friend const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub);
friend const failable<bool> stop(QpidSubscription& qsub);
const bool owner;
qpid::client::SubscriptionManager subs;
};
/**
* Register a listener function with an AMQP queue.
*/
class Listener : public qpid::client::MessageListener {
public:
Listener(const lambda<bool(const value&, const value&)> l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) {
}
virtual void received(qpid::client::Message& msg) {
// Call the listener function
const value k(scheme::readValue(msg.getDeliveryProperties().getRoutingKey().c_str()));
const value v(scheme::readValue(msg.getData().c_str()));
const bool r = l(k, v);
if (!r) {
try {
subs.cancel(msg.getDestination());
} catch (const qpid::Exception& e) {
mkfailure<bool>(string("Qpid failure: ") + e.what());
}
}
}
private:
const lambda<bool(const value&, const value&)> l;
qpid::client::SubscriptionManager& subs;
};
const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub) {
debug("queue::listen");
Listener listener(l, qsub.subs);
try {
qsub.subs.subscribe(listener, c_str(name));
qsub.subs.run();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
debug("queue::listen::stopped");
return true;
}
/**
* Stop an AMQP subscription.
*/
const failable<bool> stop(QpidSubscription& qsub) {
debug("queue::stop");
try {
qsub.subs.stop();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
debug("queue::stopped");
return true;
}
}
}
// Re-enable conversion and redundant declarations warnings
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic warning "-Wconversion"
#pragma GCC diagnostic warning "-Wredundant-decls"
#endif
#endif /* tuscany_qpid_hpp */

View file

@ -0,0 +1,24 @@
#!/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.
# Start qpidd
here=`readlink -f $0`; here=`dirname $here`
qpid_prefix=`cat $here/qpidc.prefix`
$qpid_prefix/sbin/qpidd &

View file

@ -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.
# Stop qpidd
here=`readlink -f $0`; here=`dirname $here`
qpid_prefix=`cat $here/qpidc.prefix`
qpidd="$qpid_prefix/sbin/qpidd"
kill `ps -ef | grep -v grep | grep "${qpidd}" | awk '{ print $2 }'`

View file

@ -0,0 +1,158 @@
/*
* 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$ */
/**
* AMQP queue listener component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "parallel.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
/**
* A relay function that posts the AMQP messages it receives to a relay component reference.
*/
class relay {
public:
relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
}
const bool operator()(const value& k, const value& v) const {
debug(k, "queue::relay::key");
debug(v, "queue::relay::value");
const value res = rel(mklist<value>("post", isList(k)? (list<value>)k : mklist<value>(k), v));
return true;
}
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an AMQP queue.
*/
class subscribe {
public:
subscribe(const string& qname, const lambda<bool(const value&, const value&)>& l, const QpidSubscription& qsub) : qname(qname), l(l), qsub(qsub) {
}
const failable<bool> operator()() const {
gc_pool pool;
debug(qname, "queue::subscribe::listen");
const failable<bool> r = listen(qname, l, const_cast<QpidSubscription&>(qsub));
debug(qname, "queue::subscribe::stopped");
return r;
}
private:
const string qname;
const lambda<bool(const value&, const value&)> l;
const QpidSubscription qsub;
};
/**
* Listener lambda function, responsible for starting an AMQP subscription in a worker thread, and
* apply any function calls to the listener component. The only supported function is stop(),
* called to stop the listener component and shutdown the worker thread.
*/
class listener {
public:
listener(QpidConnection& qc, QpidSession& qs, QpidSubscription& qsub, worker& w) : qc(qc), qs(qs), qsub(qsub), w(w) {
}
const value operator()(const list<value>& params) const {
const tuscany::value func(car(params));
// Stop the component
if (func != "stop")
return tuscany::mkfailure<tuscany::value>();
debug("queue::listener::stop");
// TODO check why stop() and close() hang in child processes
stop(const_cast<QpidSubscription&>(qsub));
close(const_cast<QpidSession&>(qs));
close(const_cast<QpidConnection&>(qc));
cancel(const_cast<worker&>(w));
debug("queue::listener::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
QpidConnection qc;
QpidSession qs;
QpidSubscription qsub;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the relay reference and the AMQP key and queue name
const value rel = car(params);
const value pk = ((lambda<value(list<value>)>)cadr(params))(list<value>());
const value key = isList(pk)? (list<value>)pk : mklist<value>(pk);
const value qname = ((lambda<value(list<value>)>)caddr(params))(list<value>());
// Create an AMQP session
QpidConnection qc(false);
QpidSession qs(qc, false);
// Declare the configured AMQP key / queue pair
declareQueue(key, qname, qs);
// Listen and relay messages in a worker thread
QpidSubscription qsub(qs, false);
worker w(3);
const lambda<bool(const value&, const value&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(qname, rl, qsub)));
// Return the listener component lambda function
return value(lambda<value(const list<value>&)>(listener(qc, qs, qsub, w)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::queue::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,72 @@
/*
* 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$ */
/**
* AMQP queue sender component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
/**
* Post an item to a queue.
*/
const failable<value> post(const list<value>& params) {
QpidConnection qc;
QpidSession qs(qc);
// Post the item
const value pk = ((lambda<value(list<value>)>)caddr(params))(list<value>());
const value key = isList(pk)? append<value>(pk, (list<value>)car(params)) : cons<value>(pk, (list<value>)car(params));
debug(key, "queue::post::key");
debug(cadr(params), "queue::post::value");
const failable<bool> r = post(key, cadr(params), qs);
if (!hasContent(r))
return mkfailure<value>(reason(r));
return key;
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "post")
return tuscany::queue::post(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="queue">
<component name="print-sender">
<implementation.cpp path=".libs" library="libqueue-sender"/>
<property name="key">print</property>
<service name="print-sender">
<t:binding.http uri="print-sender"/>
</service>
</component>
<component name="print-listener">
<implementation.cpp path=".libs" library="libqueue-listener"/>
<property name="key">print</property>
<property name="queue">printq</property>
<reference name="relay" target="print"/>
</component>
<component name="print">
<t:implementation.scheme script="server-test.scm"/>
<service name="print">
<t:binding.http uri="print"/>
</service>
<reference name="report" target="report-sender"/>
</component>
<component name="report-sender">
<implementation.cpp path=".libs" library="libqueue-sender"/>
<property name="key">report</property>
<service name="report-sender">
<t:binding.http uri="report-sender"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./qpidd-start
sleep 1
# Test
./qpid-test 2>/dev/null
rc=$?
# Cleanup
./qpidd-stop
sleep 1
return $rc

View file

@ -0,0 +1,43 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite queue.composite
EOF
./qpidd-start
sleep 1
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 1
./qpidd-stop
sleep 1
return $rc

View file

@ -0,0 +1,20 @@
; 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.
; Queue test case
(define (post key val report) (report "post" '() val))

View file

@ -0,0 +1,43 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
if WANT_SQLDB
INCLUDES = -I${PGSQL_INCLUDE}
#comp_SCRIPTS = pgsql-start pgsql-stop
compdir=$(prefix)/components/sqldb
comp_DATA = pgsql.prefix
pgsql.prefix: $(top_builddir)/config.status
echo ${PGSQL_PREFIX} >pgsql.prefix
comp_LTLIBRARIES = libsqldb.la
libsqldb_la_SOURCES = sqldb.cpp
libsqldb_la_LDFLAGS = -L${PGSQL_LIB} -R${PGSQL_LIB} -lpq
pgsql_test_SOURCES = pgsql-test.cpp
pgsql_test_LDFLAGS = -L${PGSQL_LIB} -R${PGSQL_LIB} -lpq
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
noinst_PROGRAMS = pgsql-test client-test
TESTS = sqldb-test server-test
endif

View file

@ -0,0 +1,130 @@
/*
* 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 SQLDB component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/curl.hpp"
namespace tuscany {
namespace sqldb {
const string uri("http://localhost:8090/sqldb");
bool testSqlDb() {
http::CURLSession cs;
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);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == a);
}
const list<value> j = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55"));
const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == b);
}
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(!hasContent(val));
}
return true;
}
struct getLoop {
const string path;
const value entry;
http::CURLSession cs;
getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
}
const bool operator()() const {
const failable<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs;
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
cout << "Sqldb get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::sqldb::testSqlDb();
tuscany::sqldb::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,25 @@
#!/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.
# Run SQL command
here=`readlink -f $0`; here=`dirname $here`
pgsql_prefix=`cat $here/pgsql.prefix`
$pgsql_prefix/bin/psql -c "$1" db

View file

@ -0,0 +1,37 @@
#!/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.
# Start postgresql
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
pgsql_prefix=`cat $here/pgsql.prefix`
mkdir -p $root/sqldb
mkdir -p $root/logs
if [ ! -f $root/sqldb/postgresql.conf ]; then
$pgsql_prefix/bin/pg_ctl init -D $root/sqldb 1>/dev/null 2>&1
createdb="true"
fi
$pgsql_prefix/bin/pg_ctl start -D $root/sqldb -l $root/logs/postgresql 1>/dev/null 2>&1
sleep 2
if [ "$createdb" = "true" ]; then
$pgsql_prefix/bin/createdb db 1>/dev/null 2>&1
fi

View file

@ -0,0 +1,28 @@
#!/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.
# Stop postgresql
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
pgsql_prefix=`cat $here/pgsql.prefix`
mkdir -p $root/sqldb
mkdir -p $root/logs
$pgsql_prefix/bin/pg_ctl stop -D $root/sqldb 1>/dev/null 2>&1

View file

@ -0,0 +1,82 @@
/*
* 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 PostgreSQL access functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "pgsql.hpp"
namespace tuscany {
namespace pgsql {
bool testPGSql() {
PGSql pg("dbname=db", "test");
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), pg)));
assert((get(k, pg)) == value(string("AAA")));
assert(hasContent(put(k, string("aaa"), pg)));
assert((get(k, pg)) == value(string("aaa")));
assert(hasContent(del(k, pg)));
assert(!hasContent(get(k, pg)));
return true;
}
struct getLoop {
const value k;
PGSql& pg;
getLoop(const value& k, PGSql& pg) : k(k), pg(pg) {
}
const bool operator()() const {
assert((get(k, pg)) == value(string("CCC")));
return true;
}
};
bool testGetPerf() {
const value k = mklist<value>("c");
PGSql pg("dbname=db", "test");
assert(hasContent(post(k, string("CCC"), pg)));
const lambda<bool()> gl = getLoop(k, pg);
cout << "PGSql get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::pgsql::testPGSql();
tuscany::pgsql::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,227 @@
/*
* 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$ */
#ifndef tuscany_pgsql_hpp
#define tuscany_pgsql_hpp
#include <libpq-fe.h>
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace pgsql {
/**
* Return and clear a Postgres result failure.
*/
const string pgfailure(PGresult* r) {
const string e = PQresultErrorMessage(r);
PQclear(r);
return e;
}
/**
* Represents a PGSql connection.
*/
class PGSql {
public:
PGSql() : owner(false) {
}
PGSql(const string& conninfo, const string& table) : owner(true), conninfo(conninfo), table(table) {
init();
}
PGSql(const PGSql& c) : owner(false) {
conninfo = c.conninfo;
conn = c.conn;
table = c.table;
}
~PGSql() {
if (!owner)
return;
PQfinish(conn);
}
private:
bool owner;
PGconn *conn;
string conninfo;
string table;
friend const failable<bool> post(const value& key, const value& val, const PGSql& pgsql);
friend const failable<bool> put(const value& key, const value& val, const PGSql& pgsql);
friend const failable<value> get(const value& key, const PGSql& pgsql);
friend const failable<bool> del(const value& key, const PGSql& pgsql);
/**
* Initialize the database connection
*/
const failable<bool> init() {
conn = PQconnectdb(c_str(conninfo));
if (PQstatus(conn) != CONNECTION_OK)
return mkfailure<bool>(string("Could not connect to database: ") + PQerrorMessage(conn));
// Find the name of the first column in the target table
// Assume that's the key we need to use
string ks = string("select a.attname from pg_attribute a, pg_class c where a.attrelid = c.relfilenode and c.relname = '") + table + string("' and a.attnum in (1, 2) order by a.attnum;");
PGresult* kr = PQexec(conn, c_str(ks));
if (PQresultStatus(kr) != PGRES_TUPLES_OK)
return mkfailure<bool>(string("Could not execute column select statement: ") + pgfailure(kr));
if (PQntuples(kr) != 2) {
PQclear(kr);
return mkfailure<bool>(string("Could not find table key and value column names"));
}
const string kname = PQgetvalue(kr, 0, 0);
const string vname = PQgetvalue(kr, 1, 0);
PQclear(kr);
// Prepare the post, put, get and delete statements
{
PGresult* r = PQprepare(conn, "post", c_str(string("insert into ") + table + string(" values($1, $2);")), 2, NULL);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not prepare post SQL statement: ") + pgfailure(r));
PQclear(r);
}
{
PGresult* r = PQprepare(conn, "put", c_str(string("update ") + table + string(" set ") + vname + string(" = $2 where ") + kname + string(" = $1;")), 2, NULL);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not prepare put SQL statement: ") + pgfailure(r));
PQclear(r);
}
{
PGresult* r = PQprepare(conn, "get", c_str(string("select * from ") + table + string(" where ") + kname + string(" = $1;")), 1, NULL);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not prepare get SQL statement: ") + pgfailure(r));
PQclear(r);
}
{
PGresult* r = PQprepare(conn, "delete", c_str(string("delete from ") + table + string(" where ") + kname + string(" = $1;")), 1, NULL);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not prepare delete SQL statement: ") + pgfailure(r));
PQclear(r);
}
return true;
}
};
/**
* Post a new item to the database.
*/
const failable<bool> post(const value& key, const value& val, const PGSql& pgsql) {
debug(key, "pgsql::post::key");
debug(val, "pgsql::post::value");
debug(pgsql.table, "pgsql::post::table");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const char* params[2] = { c_str(ks), c_str(vs) };
PGresult* r = PQexecPrepared(pgsql.conn, "post", 2, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not execute post SQL statement: ") + pgfailure(r));
PQclear(r);
debug(true, "pgsql::post::result");
return true;
}
/**
* Update an item in the database. If the item doesn't exist it is added.
*/
const failable<bool> put(const value& key, const value& val, const PGSql& pgsql) {
debug(key, "pgsql::put::key");
debug(val, "pgsql::put::value");
debug(pgsql.table, "pgsql::put::table");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const char* params[2] = { c_str(ks), c_str(vs) };
PGresult* r = PQexecPrepared(pgsql.conn, "put", 2, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not execute put SQL statement: ") + pgfailure(r));
const string t = PQcmdTuples(r);
if (t != "0") {
PQclear(r);
debug(true, "pgsql::put::result");
return true;
}
PQclear(r);
PGresult* pr = PQexecPrepared(pgsql.conn, "post", 2, params, NULL, NULL, 0);
if (PQresultStatus(pr) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not execute post SQL statement: ") + pgfailure(pr));
PQclear(pr);
debug(true, "pgsql::put::result");
return true;
}
/**
* Get an item from the database.
*/
const failable<value> get(const value& key, const PGSql& pgsql) {
debug(key, "pgsql::get::key");
debug(pgsql.table, "pgsql::get::table");
const string ks(scheme::writeValue(key));
const char* params[1] = { c_str(ks) };
PGresult* r = PQexecPrepared(pgsql.conn, "get", 1, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_TUPLES_OK)
return mkfailure<value>(string("Could not execute get SQL statement: ") + pgfailure(r));
if (PQntuples(r) < 1) {
PQclear(r);
return mkfailure<value>(string("Could not get entry: ") + PQerrorMessage(pgsql.conn));
}
const char* data = PQgetvalue(r, 0, 1);
const value val(scheme::readValue(string(data)));
PQclear(r);
debug(val, "pgsql::get::result");
return val;
}
/**
* Delete an item from the database
*/
const failable<bool> del(const value& key, const PGSql& pgsql) {
debug(key, "pgsql::delete::key");
debug(pgsql.table, "pgsql::delete::table");
const string ks(scheme::writeValue(key));
const char* params[1] = { c_str(ks) };
PGresult* r = PQexecPrepared(pgsql.conn, "delete", 1, params, NULL, NULL, 0);
if (PQresultStatus(r) != PGRES_COMMAND_OK)
return mkfailure<bool>(string("Could not execute delete SQL statement: ") + pgfailure(r));
PQclear(r);
debug(true, "pgsql::delete::result");
return true;
}
}
}
#endif /* tuscany_pgsql_hpp */

View file

@ -0,0 +1,43 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite sqldb.composite
EOF
./pgsql-start tmp
./pgsql "drop table test;" 1>/dev/null 2>&1
./pgsql "create table test(key text, value text);" 1>/dev/null 2>&1
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
./pgsql-stop tmp
sleep 2
return $rc

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./pgsql-start tmp
./pgsql "drop table test;" 1>/dev/null 2>&1
./pgsql "create table test(key text, value text);" 1>/dev/null 2>&1
# Test
./pgsql-test 2>/dev/null
rc=$?
# Cleanup
./pgsql-stop tmp
return $rc

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="sqldb">
<component name="sqldb">
<implementation.cpp path=".libs" library="libsqldb"/>
<property name="conninfo">dbname=db</property>
<property name="table">test</property>
<service name="sqldb">
<t:binding.http uri="sqldb"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,135 @@
/*
* 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$ */
/**
* PostgreSQL-based database component implementation.
*/
#include <apr_uuid.h>
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "pgsql.hpp"
namespace tuscany {
namespace sqldb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, pgsql::PGSql& pg) {
return pgsql::get(car(params), pg);
}
/**
* Post an item to the database.
*/
const value uuidValue() {
apr_uuid_t uuid;
apr_uuid_get(&uuid);
char buf[APR_UUID_FORMATTED_LENGTH];
apr_uuid_format(buf, &uuid);
return value(string(buf, APR_UUID_FORMATTED_LENGTH));
}
const failable<value> post(const list<value>& params, pgsql::PGSql& pg) {
const value id = append<value>(car(params), mklist(uuidValue()));
const failable<bool> val = pgsql::post(id, cadr(params), pg);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return id;
}
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, pgsql::PGSql& pg) {
const failable<bool> val = pgsql::put(car(params), cadr(params), pg);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, pgsql::PGSql& pg) {
const failable<bool> val = pgsql::del(car(params), pg);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Component implementation lambda function.
*/
class applySqldb {
public:
applySqldb(pgsql::PGSql& pg) : pg(pg) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "get")
return get(cdr(params), pg);
if (func == "post")
return post(cdr(params), pg);
if (func == "put")
return put(cdr(params), pg);
if (func == "delete")
return del(cdr(params), pg);
return tuscany::mkfailure<tuscany::value>();
}
private:
pgsql::PGSql& pg;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to the configured database and table
const value conninfo = ((lambda<value(list<value>)>)car(params))(list<value>());
const value table = ((lambda<value(list<value>)>)cadr(params))(list<value>());
pgsql::PGSql& pg = *(new (gc_new<pgsql::PGSql>()) pgsql::PGSql(conninfo, table));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applySqldb(pg)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::sqldb::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,20 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
if WANT_NOSQLDB
endif

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="store">
<component name="store">
<implementation.cpp path=".libs" library="libstore"/>
<service name="store">
<t:binding.http uri="store"/>
</service>
</component>
</composite>

View file

@ -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.
if WANT_WEBSERVICE
INCLUDES = -I${AXIS2C_INCLUDE}
comp_DATA = axis2c.prefix
compdir=$(prefix)/components/webservice
axis2c.prefix: $(top_builddir)/config.status
echo ${AXIS2C_PREFIX} >axis2c.prefix
comp_LTLIBRARIES = libwebservice-client.la libwebservice-listener.la libaxis2-dispatcher.la libaxis2-service.la
libwebservice_client_la_SOURCES = webservice-client.cpp
libwebservice_client_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
libwebservice_listener_la_SOURCES = webservice-listener.cpp
libwebservice_listener_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
libaxis2_dispatcher_la_SOURCES = axis2-dispatcher.cpp
libaxis2_dispatcher_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
libaxis2_service_la_SOURCES = axis2-service.cpp
libaxis2_service_la_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
axiom_test_SOURCES = axiom-test.cpp
axiom_test_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
axis2_test_SOURCES = axis2-test.cpp
axis2_test_LDFLAGS = -lxml2 -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${AXIS2C_LIB} -R${AXIS2C_LIB} -laxis2_engine -laxis2_axiom -laxutil
noinst_PROGRAMS = axiom-test axis2-test client-test
TESTS = axiom-test echo-test server-test
endif

View file

@ -0,0 +1,85 @@
/*
* 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 Web service Axiom support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
const string customerElement =
"<customer>"
"<name>jdoe</name>"
"<address><city>san francisco</city><state>ca</state></address>"
"<account><id>1234</id><balance>1000</balance></account>"
"<account><id>6789</id><balance>2000</balance></account>"
"<account><id>4567</id><balance>3000</balance></account>"
"</customer>";
bool testAxiom() {
const Axis2Context ax;
{
const failable<axiom_node_t*> n = stringToAxiomNode(customerElement, ax);
assert(hasContent(n));
const failable<const string> c = axiomNodeToString(content(n), ax);
assert(hasContent(c));
assert(content(c) == customerElement);
}
{
const list<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "text" + string("Hello World!")));
const failable<axiom_node_t*> n = valuesToAxiomNode(arg, ax);
assert(hasContent(n));
const failable<const string> x = axiomNodeToString(content(n), ax);
assert(hasContent(x));
assert(content(x) == "<ns1:echoString xmlns:ns1=\"http://ws.apache.org/axis2/services/echo\"><text>Hello World!</text></ns1:echoString>");
const failable<const list<value> > l = axiomNodeToValues(content(n), ax);
assert(hasContent(l));
assert(l == arg);
}
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::webservice::testAxiom();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,55 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Generate an Axis2 server conf
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
axis2_prefix=`cat axis2c.prefix`
# Create an Axis2 home directory
mkdir -p $root/axis2c
ln -f -s $axis2_prefix/lib $root/axis2c/lib
mkdir -p $root/axis2c/logs
mkdir -p $root/axis2c/modules
ln -f -s $axis2_prefix/modules/addressing $root/axis2c/modules/addressing
ln -f -s $axis2_prefix/modules/logging $root/axis2c/modules/logging
mkdir -p $root/axis2c/services
# Install Tuscany Axis2 module and service
mkdir -p $root/axis2c/modules/tuscany
ln -f -s $here/.libs/libaxis2-dispatcher.so $root/axis2c/modules/tuscany/libaxis2-dispatcher.so
ln -f -s $here/module.xml $root/axis2c/modules/tuscany/module.xml
mkdir -p $root/axis2c/services/tuscany
ln -f -s $here/.libs/libaxis2-service.so $root/axis2c/services/tuscany/libaxis2-service.so
ln -f -s $here/services.xml $root/axis2c/services/tuscany/services.xml
cp $here/axis2.xml $root/axis2c/axis2.xml
# Configure HTTPD Axis2 module
cat >>$root/conf/httpd.conf <<EOF
# Support for Web Services
SCASetEnv AXIS2C_HOME $root/axis2c
LoadModule axis2_module $root/axis2c/lib/libmod_axis2.so
Axis2RepoPath $root/axis2c
Axis2LogFile $root/axis2c/logs/mod_axis2.log
Axis2LogLevel debug
<Location /axis2>
SetHandler axis2_module
</Location>
EOF

View file

@ -0,0 +1,138 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Axis2/C module that dispatches all server requests to the Tuscany Axis/2C service.
*/
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
/**
* Determine the service and operation to dispatch a request to.
*/
axis2_svc_t* AXIS2_CALL dispatchFindService(axis2_msg_ctx_t* msg_ctx, const axutil_env_t* env) {
const axis2_conf_ctx_t* conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
const axis2_conf_t* conf = axis2_conf_ctx_get_conf(conf_ctx, env);
axis2_svc_t* svc = axis2_conf_get_svc(conf, env, "TuscanyService");
return svc;
}
axis2_op_t *AXIS2_CALL dispatchFindOp(unused axis2_msg_ctx_t* msg_ctx, const axutil_env_t* env, axis2_svc_t* svc) {
axutil_qname_t* op_qname = axutil_qname_create(env, "execute", NULL, NULL);
axis2_op_t *op = axis2_svc_get_op_with_name(svc, env, axutil_qname_get_localpart(op_qname, env));
axutil_qname_free(op_qname, env);
return op;
}
/**
* Dispatcher invoke function, called by Axis2/C.
*/
axis2_status_t AXIS2_CALL dispatchInvoke( struct axis2_handler* handler, const axutil_env_t* env, axis2_msg_ctx_t* msg_ctx) {
if (!(axis2_msg_ctx_get_server_side(msg_ctx, env)))
return AXIS2_SUCCESS;
axis2_msg_ctx_set_find_svc(msg_ctx, env, dispatchFindService);
axis2_msg_ctx_set_find_op(msg_ctx, env, dispatchFindOp);
return axis2_disp_find_svc_and_op(handler, env, msg_ctx);
}
/**
* Create a dispatch handler.
*/
AXIS2_EXPORT axis2_handler_t* AXIS2_CALL dispatchHandler(const axutil_env_t* env, unused axutil_string_t* name) {
axis2_handler_t *handler = axis2_handler_create(env);
if (handler == NULL)
return NULL;
axis2_handler_set_invoke(handler, env, dispatchInvoke);
return handler;
}
/**
* Initialize dispatch module.
*/
axis2_status_t AXIS2_CALL dispatchInit(unused axis2_module_t * module, unused const axutil_env_t * env, unused axis2_conf_ctx_t * conf_ctx, unused axis2_module_desc_t * module_desc) {
return AXIS2_SUCCESS;
}
/**
* Initialize dispatch module function map.
*/
axis2_status_t AXIS2_CALL dispatchFuncMap(axis2_module_t * module, const axutil_env_t * env) {
module->handler_create_func_map = axutil_hash_make(env);
axutil_hash_set(module->handler_create_func_map, "TuscanyDispatcher", AXIS2_HASH_KEY_STRING, (const void *)dispatchHandler);
return AXIS2_SUCCESS;
}
/**
* Shutdown dispatch module.
*/
axis2_status_t AXIS2_CALL dispatchShutdown(axis2_module_t* module, const axutil_env_t* env) {
if (module->handler_create_func_map != NULL) {
axutil_hash_free(module->handler_create_func_map, env);
module->handler_create_func_map = NULL;
}
AXIS2_FREE(env->allocator, module);
return AXIS2_SUCCESS;
}
/**
* Return a new dispatch module.
*/
const axis2_module_ops_t dispatchOps = {
dispatchInit,
dispatchShutdown,
dispatchFuncMap
};
axis2_module_t * dispatchModule(const axutil_env_t* env) {
axis2_module_t *module = (axis2_module_t*)AXIS2_MALLOC(env->allocator, sizeof(axis2_module_t));
if (module == NULL)
return NULL;
module->ops = &dispatchOps;
module->handler_create_func_map = NULL;
return module;
}
}
}
extern "C"
{
/**
* Axis2/C module entry point functions.
*/
AXIS2_EXPORT int axis2_get_instance(axis2_module_t** inst, const axutil_env_t* env) {
*inst = tuscany::webservice::dispatchModule(env);
if(*inst == NULL)
return AXIS2_FAILURE;
return AXIS2_SUCCESS;
}
AXIS2_EXPORT int axis2_remove_instance(axis2_module_t* inst, const axutil_env_t* env) {
if (inst != NULL)
return tuscany::webservice::dispatchShutdown(inst, env);
return AXIS2_FAILURE;
}
}

View file

@ -0,0 +1,151 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Axis2/C service implementation that dispatches requests to SCA Web service components.
*/
#include "value.hpp"
#include "string.hpp"
#include "../../modules/http/httpd.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
/**
* Initialize the service.
*/
int AXIS2_CALL serviceInit(unused axis2_svc_skeleton_t* svc_skeleton, unused const axutil_env_t* env) {
return AXIS2_SUCCESS;
}
/**
* Free the service.
*/
int AXIS2_CALL serviceFree(axis2_svc_skeleton_t* svc_skeleton, const axutil_env_t* env) {
if (svc_skeleton)
AXIS2_FREE(env->allocator, svc_skeleton);
return AXIS2_SUCCESS;
}
typedef struct axis2_apache2_out_transport_info {
axis2_http_out_transport_info_t out_transport_info;
request_rec *request;
axis2_char_t *encoding;
} axis2_apache2_out_transport_info_t;
extern "C" {
extern module axis2_module;
}
/**
* Service invoke function, called by Axis2/C.
*/
axiom_node_t *AXIS2_CALL serviceInvoke(unused axis2_svc_skeleton_t* svc_skeleton, const axutil_env_t* env, axiom_node_t* node, axis2_msg_ctx_t* msg_ctx) {
// Check that we have an input node
if (node == NULL || axiom_node_get_node_type(node, env) != AXIOM_ELEMENT)
return NULL;
axiom_element_t *e = (axiom_element_t *) axiom_node_get_data_element(node, env);
if (e == NULL)
return NULL;
// Get the function name
const char* func = axiom_element_get_localname(e, env);
if (func == NULL)
return NULL;
// Get the target endpoint address
const axis2_endpoint_ref_t* epr = axis2_msg_ctx_get_from(msg_ctx, env);
if (epr == NULL)
return NULL;
string address = axis2_endpoint_ref_get_address(epr, env);
// Get the underlying HTTPD request
axis2_out_transport_info_t* tinfo = axis2_msg_ctx_get_out_transport_info(msg_ctx, env);
axis2_apache2_out_transport_info_t* httpinfo = (axis2_apache2_out_transport_info_t*)tinfo;
request_rec* r = httpinfo->request;
httpdDebugRequest(r, "webservice::serviceInvoke");
// Parse the request Axiom node and construct request expression
Axis2Context ax(env);
const failable<const list<value> > lv = axiomNodeToValues(node, ax);
if (!hasContent(lv))
return NULL;
const value expr = mklist<value>(func, content(lv));
debug(expr, "webservice::serviceInvoke::expr");
// Retrieve the target lambda function from the HTTPD request and invoke it
const value* rv = const_cast<const value*>((value*)ap_get_module_config(r->request_config, &axis2_module));
cout << "relay: " << rv << endl;
const lambda<value(const list<value>&)> relay = *rv;
const value res = relay(expr);
debug(res, "webservice::serviceInvoke::result");
// Construct response Axiom node
const failable<axiom_node_t*> rnode = valuesToAxiomNode(res, ax);
if (!hasContent(rnode))
return NULL;
return content(rnode);
}
/**
* Return a new service skeleton.
*/
const axis2_svc_skeleton_ops_t serviceOps = {
serviceInit,
serviceInvoke,
NULL,
serviceFree,
NULL
};
AXIS2_EXTERN axis2_svc_skeleton_t *AXIS2_CALL serviceSkeleton(const axutil_env_t* env) {
axis2_svc_skeleton_t* svc_skeleton = (axis2_svc_skeleton_t*)AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_t));
svc_skeleton->ops = &serviceOps;
svc_skeleton->func_array = NULL;
return svc_skeleton;
}
}
}
extern "C"
{
/**
* Axis2/C service entry point functions.
*/
AXIS2_EXPORT int axis2_get_instance(struct axis2_svc_skeleton** inst, const axutil_env_t* env) {
*inst = tuscany::webservice::serviceSkeleton(env);
if (inst == NULL)
return AXIS2_FAILURE;
return AXIS2_SUCCESS;
}
AXIS2_EXPORT int axis2_remove_instance(axis2_svc_skeleton_t* inst, const axutil_env_t* env) {
if (inst != NULL)
return AXIS2_SVC_SKELETON_FREE(inst, env);
return AXIS2_FAILURE;
}
}

View file

@ -0,0 +1,71 @@
/*
* 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 WebService Axis2 client support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
bool testEval() {
const Axis2Context ax;
const value func = "http://ws.apache.org/axis2/c/samples/echoString";
const list<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "text" + string("Hello World!")));
const failable<value> rval = evalExpr(mklist<value>(func, arg, string("http://localhost:9090/axis2/services/echo")), ax);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples"))
+ (list<value>() + "text" + string("Hello World!")));
assert(content(rval) == r);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::webservice::testEval();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,194 @@
/*
* 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$ */
#ifndef tuscany_webservice_hpp
#define tuscany_webservice_hpp
/**
* Web service invocation functions using Axis2.
*/
#include "config.hpp"
// Ignore redundant declarations in Axiom headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
#include <axiom.h>
#include <axis2_client.h>
#include <axis2_module.h>
#include <axis2_addr_mod.h>
#include <axis2_conf_ctx.h>
#include <axis2_disp.h>
#include <axis2_http_out_transport_info.h>
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic warning "-Wredundant-decls"
#endif
#include "string.hpp"
#include "sstream.hpp"
#include "list.hpp"
#include "value.hpp"
#include "xml.hpp"
#include "monad.hpp"
namespace tuscany {
namespace webservice {
/**
* Represents an Axis2 runtime context.
*/
class Axis2Context {
public:
Axis2Context() : env(axutil_env_create_all("axis2.log", AXIS2_LOG_LEVEL_WARNING)), owner(true) {
}
Axis2Context(const Axis2Context& ax) : env(ax.env), owner(false) {
}
Axis2Context(const axutil_env_t* env) : env(const_cast<axutil_env_t*>(env)), owner(false) {
}
~Axis2Context() {
if (!owner || env == NULL)
return;
axutil_env_free(env);
}
private:
axutil_env_t* env;
bool owner;
friend const axutil_env_t* env(const Axis2Context& ax);
};
const axutil_env_t* env(const Axis2Context& ax) {
return ax.env;
}
/**
* Return the latest Axis2 error in an Axis2 context.
*/
const string axis2Error(const Axis2Context& ax) {
ostringstream os;
os << env(ax)->error->error_number << " : " << AXIS2_ERROR_GET_MESSAGE(env(ax)->error);
return str(os);
}
/**
* Convert a string to an Axiom node.
*/
const failable<axiom_node_t*> stringToAxiomNode(const string& s, const Axis2Context& ax) {
axiom_node_t* node = axiom_node_create_from_buffer(env(ax), const_cast<axis2_char_t*>(c_str(s)));
if (node == NULL)
return mkfailure<axiom_node_t*>(string("Couldn't convert XML to Axiom node: ") + axis2Error(ax));
return node;
}
/**
* Convert a list of values representing XML elements to an Axiom node.
*/
const failable<axiom_node_t*> valuesToAxiomNode(const list<value>& l, const Axis2Context& ax) {
const failable<list<string> > xml = writeXML(valuesToElements(l), false);
if (!hasContent(xml))
return mkfailure<axiom_node_t*>(reason(xml));
ostringstream os;
write(content(xml), os);
return stringToAxiomNode(str(os), ax);
}
/**
* Convert an axiom node to a string.
*/
const failable<const string> axiomNodeToString(axiom_node_t* node, const Axis2Context& ax) {
const char* c = axiom_node_to_string(node, env(ax));
if (c == NULL)
return mkfailure<const string>(string("Couldn't convert Axiom node to XML: ") + axis2Error(ax));
const string s(c);
AXIS2_FREE(env(ax)->allocator, const_cast<char*>(c));
return s;
}
/**
* Convert an axiom node to a list of values representing XML elements.
*/
const failable<const list<value> > axiomNodeToValues(axiom_node_t* node, const Axis2Context& ax) {
const failable<const string> s = axiomNodeToString(node, ax);
if (!hasContent(s))
return mkfailure<const list<value> >(reason(s));
istringstream is(content(s));
const failable<const list<value> > l = readXML(streamList(is));
if (!hasContent(l))
return l;
return elementsToValues(content(l));
}
/**
* Evaluate an expression in the form (soap-action-string, document, uri). Send the
* SOAP action and document to the Web Service at the given URI using Axis2.
*/
const failable<value> evalExpr(const value& expr, const Axis2Context& ax) {
debug(expr, "webservice::evalExpr::input");
// Extract func name and single argument
const value func(car<value>(expr));
const list<value> param(cadr<value>(expr));
const value uri(caddr<value>(expr));
// Create Axis2 client
axis2_svc_client_t *client = axis2_svc_client_create(env(ax), getenv("AXIS2C_HOME"));
if (client == NULL)
return mkfailure<value>("Couldn't create Axis2 client: " + axis2Error(ax));
axis2_endpoint_ref_t *epr = axis2_endpoint_ref_create(env(ax), c_str(uri));
axis2_options_t *opt = axis2_options_create(env(ax));
axis2_options_set_to(opt, env(ax), epr);
axis2_options_set_action(opt, env(ax), (const axis2_char_t*)c_str(func));
axis2_svc_client_set_options(client, env(ax), opt);
axis2_svc_client_engage_module(client, env(ax), AXIS2_MODULE_ADDRESSING);
// Construct request Axiom node
const failable<axiom_node_t*> req = valuesToAxiomNode(param, ax);
if (!hasContent(req))
return mkfailure<value>(reason(req));
// Call the Web service
axiom_node_t* res = axis2_svc_client_send_receive(client, env(ax), content(req));
if (res == NULL) {
axis2_svc_client_free(client, env(ax));
return mkfailure<value>("Couldn't invoke Axis2 service: " + axis2Error(ax));
}
// Parse result Axiom node
const failable<const list<value> > lval = axiomNodeToValues(res, ax);
if (!hasContent(lval))
return mkfailure<value>(reason(lval));
const value rval = content(lval);
debug(rval, "webservice::evalExpr::result");
// Cleanup
axis2_svc_client_free(client, env(ax));
return rval;
}
}
}
#endif /* tuscany_webservice_hpp */

View file

@ -0,0 +1,148 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<axisconfig name="Axis2/C">
<!-- ================================================= -->
<!-- Parameters -->
<!-- ================================================= -->
<!-- Uncomment following to enable MTOM support globally -->
<!--parameter name="enableMTOM" locked="false">true</parameter-->
<!-- Set the suitable size for optimum memory usage when sending large attachments -->
<!--parameter name="MTOMBufferSize" locked="false">10</parameter-->
<!--parameter name="MTOMMaxBuffers" locked="false">1000</parameter-->
<!--parameter name="EnableMTOMServiceCallback" locked="false">true</parameter-->
<!--parameter name="attachmentDIR" locked="false">/path/to/the/attachment/caching/dir/</parameter-->
<!--parameter name="MTOMCachingCallback" locked="false">/path/to/the/caching_callback</parameter-->
<!--parameter name="MTOMSendingCallback" locked="false">/path/to/the/sending_callback</parameter-->
<!-- Enable REST -->
<parameter name="enableREST" locked="false">true</parameter>
<!-- Uncomment following to persist op_ctx, useful with RM -->
<!--parameter name="persistOperationContext" locked="false">true</parameter-->
<!--if you want to extract the service archive file and work with that please uncomment this-->
<!--else , it wont extract archive file or does not take into consideration if someone drop-->
<!--exploded directory into /service directory-->
<!--<parameter name="extractServiceArchive" locked="false">true</parameter>-->
<!-- ================================================= -->
<!-- Message Receivers -->
<!-- ================================================= -->
<!-- This is the Deafult Message Receiver for the Request Response style Operations -->
<!--messageReceiver mep="INOUT" class="axis2_receivers"/-->
<!-- ================================================= -->
<!-- Transport Ins -->
<!-- ================================================= -->
<transportReceiver name="http" class="axis2_http_receiver">
<parameter name="port" locked="false">6060</parameter>
<parameter name="exposeHeaders" locked="true">false</parameter>
</transportReceiver>
<!--transportReceiver name="https" class="axis2_http_receiver">
<parameter name="port" locked="false">6060</parameter>
<parameter name="exposeHeaders" locked="true">false</parameter>
</transportReceiver-->
<!--transportReceiver name="tcp" class="axis2_tcp_receiver">
<parameter name="port" locked="false">6060</parameter>
</transportReceiver-->
<!-- ================================================= -->
<!-- Transport Outs -->
<!-- ================================================= -->
<transportSender name="http" class="axis2_http_sender">
<parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter>
<parameter name="xml-declaration" insert="false"/>
<!--parameter name="Transfer-Encoding">chunked</parameter-->
<!--parameter name="HTTP-Authentication" username="" password="" locked="true"/-->
<!--parameter name="PROXY" proxy_host="127.0.0.1" proxy_port="8080" proxy_username="" proxy_password="" locked="true"/-->
</transportSender>
<!-- Uncomment the following with appropriate parameters to enable the SSL transport sender.
Also make sure that the appropriate transport receiver is enabled above.-->
<!--transportSender name="https" class="axis2_http_sender">
<parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter>
<parameter name="xml-declaration" insert="false"/>
</transportSender>
<parameter name="SERVER_CERT">/path/to/ca/certificate</parameter>
<parameter name="KEY_FILE">/path/to/client/certificate/chain/file</parameter>
<parameter name="SSL_PASSPHRASE">passphrase</parameter>
-->
<!-- Uncomment this one with the appropriate papameters to enable the TCP transport Sender-->
<!--transportSender name="tcp" class="axis2_tcp_sender">
<parameter name="PROTOCOL" locked="false">TCP</parameter>
<parameter name="xml-declaration" insert="false"/>
</transportSender-->
<!-- ================================================= -->
<!-- Global Modules -->
<!-- ================================================= -->
<!-- Comment this to disable Addressing -->
<module ref="addressing"/>
<!-- Tuscany dispatcher module -->
<module ref="tuscany"/>
<!--Configuring module , providing paramters for modules whether they refer or not-->
<!--<moduleConfig name="addressing">-->
<!--<parameter name="addressingPara" locked="false">N/A</parameter>-->
<!--</moduleConfig>-->
<!-- ================================================= -->
<!-- Phases -->
<!-- ================================================= -->
<phaseOrder type="inflow">
<!-- System pre defined phases -->
<phase name="Transport"/>
<phase name="PreDispatch"/>
<phase name="Dispatch"/>
<phase name="PostDispatch"/>
<!--phase name="Security"/-->
<!-- End system pre defined phases -->
<!-- After PostDispatch phase, module or service author can add any phase as required -->
<!-- User defined phases could be added here -->
<!--phase name="userphase1"/-->
</phaseOrder>
<phaseOrder type="outflow">
<!-- User defined phases could be added here -->
<!--phase name="userphase1"/-->
<!--system predefined phase-->
<phase name="MessageOut"/>
<!--phase name="Security"/-->
</phaseOrder>
<phaseOrder type="INfaultflow">
<!-- User defined phases could be added here -->
<!--phase name="userphase1"/-->
</phaseOrder>
<phaseOrder type="Outfaultflow">
<!-- User defined phases could be added here -->
<!--phase name="userphase1"/-->
<phase name="MessageOut"/>
</phaseOrder>
</axisconfig>

View file

@ -0,0 +1,94 @@
/*
* 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 Web service component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/curl.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
bool testModAxis2() {
const Axis2Context ax;
const value func = "http://ws.apache.org/axis2/c/samples/echoString";
const list<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "text" + string("Hello World!")));
const failable<value> rval = evalExpr(mklist<value>(func, arg, string("http://localhost:8090/echo-listener")), ax);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "text" + string("Hello World!")));
assert(content(rval) == r);
return true;
}
bool testEval() {
http::CURLSession cs;
const value func = "http://ws.apache.org/axis2/c/samples/echoString";
const list<value> arg = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
+ (list<value>() + "text" + string("Hello World!")));
const failable<value> rval = http::evalExpr(mklist<value>(func, arg), "http://localhost:8090/echo-client", cs);
assert(hasContent(rval));
const list<value> r = mklist<value>(
list<value>() + "ns1:echoString"
+ (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples"))
+ (list<value>() + "text" + string("Hello World!")));
assert(content(rval) == r);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::webservice::testModAxis2();
tuscany::webservice::testEval();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,37 @@
#!/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
axis2_prefix=`cat axis2c.prefix`
export AXIS2C_HOME=$axis2_prefix
axis2="$axis2_prefix/bin/axis2_http_server"
pwd=`pwd`
cd "$axis2_prefix/bin"
$axis2 &
cd $pwd
sleep 1
# Test
./axis2-test 2>/dev/null
rc=$?
# Cleanup
kill `ps -f | grep -v grep | grep "$axis2" | awk '{ print $2 }'`
sleep 1
return $rc

View file

@ -0,0 +1,25 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<module name="tuscany" class="axis2-dispatcher">
<inflow>
<handler name="TuscanyDispatcher" class="axis2-dispatcher">
<order phase="Dispatch"/>
</handler>
</inflow>
</module>

View file

@ -0,0 +1,49 @@
#!/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
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
./axis2-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite webservice.composite
EOF
../../modules/http/httpd-start tmp
axis2_prefix=`cat axis2c.prefix`
export AXIS2C_HOME=$axis2_prefix
axis2="$axis2_prefix/bin/axis2_http_server"
pwd=`pwd`
cd "$axis2_prefix/bin"
$axis2 &
cd $pwd
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
kill `ps -f | grep -v grep | grep "${axis2}" | awk '{ print $2 }'`
../../modules/http/httpd-stop tmp
sleep 2
return $rc

View file

@ -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.
; Web service test case
(define (echoString x) x)

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<serviceGroup>
<service name="TuscanyService">
<parameter name="ServiceClass" locked="xsd:false">axis2-service</parameter>
<operation name="execute"/>
</service>
</serviceGroup>

View file

@ -0,0 +1,65 @@
/*
* 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$ */
/**
* Web service client component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
/**
* Apply a function provided by a remote Web service using Axis2.
*/
const failable<value> apply(const value& func, const list<value>& params) {
const Axis2Context ax;
// Extract parameters
const value doc = car<value>(params);
const lambda<value(const list<value>&)> l = cadr<value>(params);
// Call the URI property lambda function to get the configured URI
const value uri = l(list<value>());
// Evaluate using Axis2
return evalExpr(mklist<value>(func, doc, uri), ax);
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::mkfailure<tuscany::value>();
return tuscany::webservice::apply(func, cdr(params));
}
}

View file

@ -0,0 +1,86 @@
/*
* 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$ */
/**
* Web service listener component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/http/httpd.hpp"
#include "axis2.hpp"
namespace tuscany {
namespace webservice {
/**
* Redirect an HTTP request to the Axis2/C HTTPD module. The given relay lambda function
* is stored in the HTTPD request, for later retrieval by the Axis2 service to relay the request
* to a target component.
*/
extern "C" {
extern module axis2_module;
}
const value redirectToAxis2(const string& uri, request_rec* r, const value& relay) {
const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r);
if (!hasContent(nr))
return value(reason(nr));
ap_set_module_config(content(nr)->request_config, &axis2_module, const_cast<void*>((const void*)&relay));
return value(httpd::internalRedirect(content(nr)));
}
/**
* Handle an HTTP request.
*/
const failable<value> handle(const list<value>& params) {
// Extract HTTPD request from the params
request_rec* r = httpd::request(car(params));
httpdDebugRequest(r, "webservice::handle");
// Extract the relay lambda from the params and store it in the HTTPD request,
// for later retrieval by our Axis2 service
const value relay = cadr(params);
cout << "relay: " << &relay << endl;
// Redirect HTTPD request to Mod-axis2
if (r->args == NULL)
return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri)), r, relay);
return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri), string(r->args)), r, relay);
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "handle")
return tuscany::webservice::handle(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="webservice-client">
<component name="webservice-client">
<implementation.cpp path=".libs" library="libwebservice-client"/>
<property name="uri">http://localhost:9090/axis2/services/echo</property>
<service name="webservice-client">
<t:binding.jsonrpc uri="echo-client"/>
</service>
</component>
<component name="webservice-listener">
<implementation.cpp path=".libs" library="libwebservice-listener"/>
<service name="webservice-listener">
<t:binding.http uri="echo-listener"/>
</service>
<reference name="relay" target="echo"/>
</component>
<component name="echo">
<t:implementation.scheme script="server-test.scm"/>
<service name="echo">
<t:binding.jsonrpc uri="echo"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,712 @@
# 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.
dnl run autogen.sh to generate the configure script.
AC_PREREQ(2.59)
AC_INIT(tuscany-sca, 1.0, dev@tuscany.apache.org)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_SYSTEM
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE([tar-ustar])
AC_PREFIX_DEFAULT(/usr/local/tuscany/sca)
# Use GCC 4.5 if available
if test -x "/usr/bin/gcc-4.5"; then
CXX=/usr/bin/g++-4.5
CPP=/usr/bin/cpp-4.5
CC=/usr/bin/gcc-4.5
fi
# Check for required programs.
AC_MSG_NOTICE([checking for programs])
AC_PROG_CXX
AC_PROG_AWK
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
# 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, [running on Darwin])
AC_MSG_RESULT(yes)
AC_SUBST([libsuffix],[".dylib"])
AM_CONDITIONAL([DARWIN], true)
else
AC_MSG_RESULT(no)
AC_SUBST([libsuffix],[".so"])
AM_CONDITIONAL([DARWIN], false)
fi
# Configure path to CURL.
AC_MSG_CHECKING([for curl])
AC_ARG_WITH([curl], [AC_HELP_STRING([--with-curl=PATH], [path to installed curl [default=/usr]])], [
CURL_PREFIX="${withval}"
LIBCURL_INCLUDE="${withval}/include"
LIBCURL_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
CURL_PREFIX="/usr"
LIBCURL_INCLUDE="/usr/include"
LIBCURL_LIB="/usr/lib"
AC_MSG_RESULT(/usr)
])
AC_SUBST(CURL_PREFIX)
AC_SUBST(LIBCURL_INCLUDE)
AC_SUBST(LIBCURL_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"
LIBXML2_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
LIBXML2_INCLUDE="/usr/include/libxml2"
LIBXML2_LIB="/usr/lib"
AC_MSG_RESULT(/usr)
])
AC_SUBST(LIBXML2_INCLUDE)
AC_SUBST(LIBXML2_LIB)
# Configure path to libmozjs includes and lib.
AC_MSG_CHECKING([for js-include])
xulrunner=`ls /usr/include | grep "xulrunner" | tail -1`
if test "$xulrunner" = ""; then
xulrunner="xulrunner-1.9.1.8"
fi
AC_ARG_WITH([js-include], [AC_HELP_STRING([--with-js-include=PATH], [path to installed SpiderMonkey include dir
[default=/usr/include/$xulrunner/unstable]])], [
JS_INCLUDE="${withval}"
AC_MSG_RESULT("${withval}")
], [
JS_INCLUDE="/usr/include/$xulrunner/unstable"
AC_MSG_RESULT(/usr/include/$xulrunner/unstable)
])
AC_MSG_CHECKING([for js-lib])
AC_ARG_WITH([js-lib], [AC_HELP_STRING([--with-js-lib=PATH], [path to installed SpiderMonkey lib dir [default=/usr/lib/$xulrunner]])], [
JS_LIB="${withval}"
AC_MSG_RESULT("${withval}")
], [
JS_LIB="/usr/lib/$xulrunner"
AC_MSG_RESULT(/usr/lib/$xulrunner)
])
AC_SUBST(JS_INCLUDE)
AC_SUBST(JS_LIB)
# Configure path to Apache APR and HTTPD includes and libs.
AC_MSG_CHECKING([for apr])
AC_ARG_WITH([apr], [AC_HELP_STRING([--with-apr=PATH], [path to installed Apache APR [default=/usr/local/apache2]])], [
APR_INCLUDE="${withval}/include"
APR_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
APR_INCLUDE="/usr/local/apache2/include"
APR_LIB="/usr/local/apache2/lib"
AC_MSG_RESULT(/usr/local/apache2/lib)
])
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 Apache HTTPD [default=/usr/local/apache2]])], [
HTTPD_PREFIX="${withval}"
HTTPD_INCLUDE="${withval}/include"
AC_MSG_RESULT("${withval}")
], [
HTTPD_PREFIX="/usr/local/apache2"
HTTPD_INCLUDE="/usr/local/apache2/include"
AC_MSG_RESULT(/usr/local/apache2/lib)
])
AC_SUBST(HTTPD_PREFIX)
AC_SUBST(HTTPD_INCLUDE)
# Configure path to memcached.
AC_MSG_CHECKING([for memcached])
AC_ARG_WITH([memcached], [AC_HELP_STRING([--with-memcached=PATH], [path to installed memcached [default=/usr]])], [
MEMCACHED_PREFIX="${withval}"
AC_MSG_RESULT("${withval}")
], [
MEMCACHED_PREFIX="/usr"
AC_MSG_RESULT(/usr)
])
AC_SUBST(MEMCACHED_PREFIX)
# Configure path to tinycdb.
AC_MSG_CHECKING([for tinycdb])
AC_ARG_WITH([tinycdb], [AC_HELP_STRING([--with-tinycdb=PATH], [path to installed tinycdb [default=/usr]])], [
TINYCDB_PREFIX="${withval}"
TINYCDB_INCLUDE="${withval}/include"
TINYCDB_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
TINYCDB_PREFIX="/usr"
TINYCDB_INCLUDE="/usr/include"
TINYCDB_LIB="/usr/lib"
AC_MSG_RESULT(/usr)
])
AC_SUBST(TINYCDB_PREFIX)
AC_SUBST(TINYCDB_INCLUDE)
AC_SUBST(TINYCDB_LIB)
# Configure TUSCANY_SCACPP path variable.
TUSCANY_SCACPP=`echo "${TUSCANY_SCACPP}"`
if test "${TUSCANY_SCACPP}" = ""; then
pwd=`pwd`
AC_SUBST([TUSCANY_SCACPP], ["${pwd}"])
fi
# Initialize default GCC C++ and LD options.
cxxflags=""
ldflags="${LDFLAGS}"
defaultlibs="${LIBS}"
# Configure default includes.
cxxflags="${cxxflags} ${INCLUDES} -I. -I${TUSCANY_SCACPP}/kernel -I${APR_INCLUDE} -I${LIBXML2_INCLUDE} -I${JS_INCLUDE} -I${LIBCURL_INCLUDE}"
# Check for libraries required by all modules and add them to LD options.
AC_MSG_NOTICE([checking for required libraries])
LIBS="-L${APR_LIB} ${defaultlibs}"
AC_CHECK_LIB([apr-1], [apr_pool_initialize], [AC_MSG_NOTICE([found])], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])])
ldflags="${ldflags} -ldl -L${APR_LIB} -R${APR_LIB} -lapr-1 -laprutil-1"
# Check for libraries only required by some modules and add their search path to LD options.
LIBS="-L${LIBCURL_LIB} ${defaultlibs}"
AC_CHECK_LIB([curl], [curl_global_init], [], [AC_MSG_ERROR([couldn't find a suitable libcurl, use --with-libcurl=PATH])])
LIBS="-L${JS_LIB} ${defaultlibs}"
AC_CHECK_LIB([mozjs], [JS_NewContext], [], [AC_MSG_ERROR([couldn't find a suitable libmozjs, use --with-js-lib=PATH])])
LIBS="-L${LIBXML2_LIB} ${defaultlibs}"
AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitable libxml2, use --with-libxml2=PATH])])
ldflags="${ldflags} -L${LIBCURL_LIB} -R${LIBCURL_LIB} -L${JS_LIB} -R${JS_LIB} -L${LIBXML2_LIB} -R${LIBXML2_LIB}"
# 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])
# 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
# Check for required library functions.
AC_MSG_NOTICE([checking for library functions])
AC_CHECK_FUNCS([gettimeofday select])
# 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
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_maintainer_mode=true
;;
esac ],
[ AC_MSG_RESULT(no)])
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
# 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
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_profiling=true
;;
esac ],
[ AC_MSG_RESULT(no)])
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
# 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
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_threads=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_threads}" = "true"; then
AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([couldn't find a suitable libpthread])])
LIBS="${defaultlibs}"
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 exuberant ctags.
TAGSFILE="`pwd`/tags"
AC_SUBST([CTAGSFLAGS], ["${CTAGSFLAGS} --c++-kinds=+p --fields=+iaS --extra=+q --append --tag-relative=yes -f ${TAGSFILE}"])
# 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
no)
AC_MSG_RESULT(no)
;;
*)
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
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_PREFIX="${withval}"
PYTHON_INCLUDE="${withval}/include"
PYTHON_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
PYTHON_PREFIX="/usr"
PYTHON_INCLUDE="/usr/include"
PYTHON_LIB="/usr/lib"
AC_MSG_RESULT(/usr)
])
AC_SUBST(PYTHON_PREFIX)
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)])
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])])
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_PREFIX="${withval}"
JAVA_INCLUDE="${withval}/include"
JAVAC="${withval}/bin/javac"
JAR="${withval}/bin/jar"
AC_MSG_RESULT("${withval}")
], [
JAVA_PREFIX="/usr/lib/jvm/default-java"
JAVA_INCLUDE="/usr/lib/jvm/default-java/include"
JAVAC="/usr/lib/jvm/default-java/bin/javac"
JAR="/usr/lib/jvm/default-java/bin/jar"
AC_MSG_RESULT(/usr/lib/jvm/default-java)
])
AC_SUBST(JAVA_PREFIX)
AC_SUBST(JAVA_INCLUDE)
AC_SUBST(JAVAC)
AC_SUBST(JAR)
# 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
# Detect most common Java VMs
if test -f "${JAVA_PREFIX}/jre/lib/i386/libjava.so"; then
if test -f "${JAVA_PREFIX}/jre/lib/i386/server/libjvm.so"; then
# Server VM
AC_MSG_NOTICE([checking for server Java VM])
JAVA_CHECK_LIB="-L${JAVA_PREFIX}/jre/lib/i386 -R${JAVA_PREFIX}/jre/lib/i386 -L${JAVA_PREFIX}/jre/lib/i386/server -R${JAVA_PREFIX}/jre/lib/i386/server"
LIBS="${JAVA_CHECK_LIB} ${default_LIBS}"
AC_CHECK_LIB([java], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -ljava -ljvm -lverify"], [], [-ljvm -lverify])
if test "${JAVA_LDFLAGS}" != ""; then
AC_DEFINE([JAVA_SERVER_VM], 1, [Server Java VM])
fi
else
if test -f "${JAVA_PREFIX}/jre/lib/i386/j9vm/libjvm.so"; then
# J9 VM
AC_MSG_NOTICE([checking for J9 Java VM])
JAVA_CHECK_LIB="-L${JAVA_PREFIX}/jre/lib/i386 -R${JAVA_PREFIX}/jre/lib/i386 -L${JAVA_PREFIX}/jre/lib/i386/j9vm -R${JAVA_PREFIX}/jre/lib/i386/j9vm"
LIBS="${JAVA_CHECK_LIB} ${default_LIBS}"
AC_CHECK_LIB([java], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -ljava -ljvm -ljsig"], [], [-ljvm -ljsig])
if test "${JAVA_LDFLAGS}" != ""; then
AC_DEFINE([JAVA_J9_VM], 1, [J9 Java VM])
fi
fi
fi
else
if test -f "${JAVA_PREFIX}/jre/bin/default/libharmonyvm.so"; then
# Apache Harmony VM
AC_MSG_NOTICE([checking for Apache Harmony Java VM])
JAVA_CHECK_LIB="-L${JAVA_PREFIX}/jre/bin -R${JAVA_PREFIX}/jre/bin -L${JAVA_PREFIX}/jre/bin/default -R${JAVA_PREFIX}/jre/bin/default"
LIBS="${JAVA_CHECK_LIB} ${default_LIBS}"
AC_CHECK_LIB([harmonyvm], [JNI_CreateJavaVM], [JAVA_LDFLAGS="${JAVA_CHECK_LIB} -lharmonyvm -lhythr -licuuc -lch ${JAVA_PREFIX}/jre/bin/default/libicudata.so.34"], [], [-lhythr -licuuc -lch ${JAVA_PREFIX}/jre/bin/default/libicudata.so.34])
if test "${JAVA_LDFLAGS}" != ""; then
AC_DEFINE([JAVA_HARMONY_VM], 1, [Apache Harmony Java VM])
fi
fi
fi
if test "${JAVA_LDFLAGS}" = ""; then
AC_MSG_ERROR([couldn't find a suitable Java JNI library, use --with-java=PATH])
fi
AC_MSG_CHECKING([for javac])
if test -x "${JAVAC}"; then
AC_MSG_RESULT("${JAVAC}")
else
AC_MSG_ERROR([couldn't find a suitable javac tool, use --with-java=PATH])
fi
AC_MSG_CHECKING([for jar])
if test -x "${JAR}"; then
AC_MSG_RESULT("${JAR}")
else
AC_MSG_ERROR([couldn't find a suitable jar tool, use --with-java=PATH])
fi
AM_CONDITIONAL([WANT_JAVA], true)
AC_DEFINE([WANT_JAVA], 1, [enable Java support])
else
AM_CONDITIONAL([WANT_JAVA], false)
JAVA_LDFLAGS=""
fi
AC_SUBST(JAVA_LDFLAGS)
# Configure path to Google AppEngine SDK.
AC_MSG_CHECKING([for gae])
AC_ARG_WITH([gae], [AC_HELP_STRING([--with-gae=PATH], [path to installed Google AppEngine 1.3.2 [default=$HOME/google_appengine]])], [
GAE_PREFIX="${withval}"
AC_MSG_RESULT("${withval}")
], [
GAE_PREFIX="$HOME/google_appengine"
AC_MSG_RESULT($HOME/google_appengine)
])
AC_SUBST(GAE_PREFIX)
# Enable support for Google AppEngine.
AC_MSG_CHECKING([whether to enable Google AppEngine support])
AC_ARG_ENABLE(gae, [AS_HELP_STRING([--enable-gae], [enable Google AppEngine support [default=no]])],
[ case "${enableval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_gae=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_gae}" = "true"; then
AM_CONDITIONAL([WANT_GAE], true)
AC_DEFINE([WANT_GAE], 1, [enable Google AppEngine support])
else
AM_CONDITIONAL([WANT_GAE], false)
fi
# Configure path to Java includes and lib.
# Configure path to Apache Axis2C includes and lib.
AC_MSG_CHECKING([for axis2c])
AC_ARG_WITH([axis2c], [AC_HELP_STRING([--with-axis2c=PATH], [path to installed Apache Axis2C [default=/usr/local/axis2c]])], [
AXIS2C_PREFIX="${withval}"
AXIS2C_INCLUDE="${withval}/include/axis2-1.6.0"
AXIS2C_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
AXIS2C_PREFIX="/usr/local/axis2c"
AXIS2C_INCLUDE="/usr/local/axis2c/include/axis2-1.6.0"
AXIS2C_LIB="/usr/local/axis2c/lib"
AC_MSG_RESULT(/usr/local/axis2c)
])
AC_SUBST(AXIS2C_PREFIX)
AC_SUBST(AXIS2C_INCLUDE)
AC_SUBST(AXIS2C_LIB)
# Enable Web service component.
AC_MSG_CHECKING([whether to enable the Web service component])
AC_ARG_ENABLE(webservice, [AS_HELP_STRING([--enable-webservice], [enable Web service component [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])])
AM_CONDITIONAL([WANT_WEBSERVICE], true)
AC_DEFINE([WANT_WEBSERVICE], 1, [enable Web service component])
else
AM_CONDITIONAL([WANT_WEBSERVICE], false)
fi
# Enable NoSQL database component.
AC_MSG_CHECKING([whether to enable the NoSQL database component])
AC_ARG_ENABLE(nosqldb, [AS_HELP_STRING([--enable-nosqldb], [enable NoSQL database component [default=no]])],
[ case "${enableval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_nosqldb=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_nosqldb}" = "true"; then
AM_CONDITIONAL([WANT_NOSQLDB], true)
AC_DEFINE([WANT_NOSQLDB], 1, [enable NoSQL database component])
else
AM_CONDITIONAL([WANT_NOSQLDB], false)
fi
# Configure path to PostgreSQL.
AC_MSG_CHECKING([for pgsql])
AC_ARG_WITH([pgsql], [AC_HELP_STRING([--with-pgsql=PATH], [path to installed PostgreSQL [default=/usr/local/pgsql]])], [
PGSQL_PREFIX="${withval}"
PGSQL_INCLUDE="${withval}/include"
PGSQL_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
PGSQL_PREFIX="/usr/local/pgsql"
PGSQL_INCLUDE="/usr/local/pgsql/include"
PGSQL_LIB="/usr/local/pgsql/lib"
AC_MSG_RESULT(/usr/local)
])
AC_SUBST(PGSQL_PREFIX)
AC_SUBST(PGSQL_INCLUDE)
AC_SUBST(PGSQL_LIB)
# Enable SQL Database component.
AC_MSG_CHECKING([whether to enable the SQL Database component])
AC_ARG_ENABLE(sqldb, [AS_HELP_STRING([--enable-sqldb], [enable SQL Database component [default=no]])],
[ case "${enableval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_sqldb=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_sqldb}" = "true"; then
AM_CONDITIONAL([WANT_SQLDB], true)
AC_DEFINE([WANT_SQLDB], 1, [enable SQL Database component])
else
AM_CONDITIONAL([WANT_SQLDB], false)
fi
# Configure path to Apache Qpid/C++.
AC_MSG_CHECKING([for qpidc])
AC_ARG_WITH([qpidc], [AC_HELP_STRING([--with-qpidc=PATH], [path to installed Apache Qpid/C++ [default=/usr/local]])], [
QPIDC_PREFIX="${withval}"
QPIDC_INCLUDE="${withval}/include"
QPIDC_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
QPIDC_PREFIX="/usr/local"
QPIDC_INCLUDE="/usr/local/include"
QPIDC_LIB="/usr/local/lib"
AC_MSG_RESULT(/usr/local)
])
AC_SUBST(QPIDC_PREFIX)
AC_SUBST(QPIDC_INCLUDE)
AC_SUBST(QPIDC_LIB)
# Enable Queue component.
AC_MSG_CHECKING([whether to enable the Queue component])
AC_ARG_ENABLE(queue, [AS_HELP_STRING([--enable-queue], [enable Queue component [default=no]])],
[ case "${enableval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_queue=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_queue}" = "true"; then
if test "${want_threads}" != "true"; then
AC_MSG_ERROR([--enable-queue requires multi-threading, use --enable-threads])
fi
LIBS="-L${QPIDC_LIB} ${default_LIBS}"
AC_CHECK_LIB([qpidclient], [_init], [], [AC_MSG_ERROR([couldn't find a suitable libqpidclient, use --with-qpidc=PATH])])
AM_CONDITIONAL([WANT_QUEUE], true)
AC_DEFINE([WANT_QUEUE], 1, [enable Queue component])
else
AM_CONDITIONAL([WANT_QUEUE], false)
fi
# Configure path to Libstrophe includes and lib.
AC_MSG_CHECKING([for libstrophe])
AC_ARG_WITH([libstrophe], [AC_HELP_STRING([--with-libstrophe=PATH], [path to libstrophe [default=${HOME}/libstrophe-bin]])], [
LIBSTROPHE_INCLUDE="${withval}/include"
LIBSTROPHE_LIB="${withval}/lib"
AC_MSG_RESULT("${withval}")
], [
LIBSTROPHE_INCLUDE="${HOME}/libstrophe-bin/include"
LIBSTROPHE_LIB="${HOME}/libstrophe-bin/lib"
AC_MSG_RESULT(${HOME}/libstrophe-bin)
])
AC_SUBST(LIBSTROPHE_INCLUDE)
AC_SUBST(LIBSTROPHE_LIB)
# Configure path to Vysper
AC_MSG_CHECKING([for vysper])
AC_ARG_WITH([vysper], [AC_HELP_STRING([--with-vysper=PATH], [path to Apache Vysper [default=${HOME}/vysper-1.0.0]])], [
VYSPER_PREFIX="${withval}"
AC_MSG_RESULT("${withval}")
], [
VYSPER_PREFIX="${HOME}/vysper-1.0.0"
AC_MSG_RESULT(${HOME}/vysper-1.0.0)
])
AC_SUBST(VYSPER_PREFIX)
# Enable Chat component.
AC_MSG_CHECKING([whether to enable the Chat component])
AC_ARG_ENABLE(chat, [AS_HELP_STRING([--enable-chat], [enable Chat component [default=no]])],
[ case "${enableval}" in
no)
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
want_chat=true
;;
esac ],
[ AC_MSG_RESULT(no)])
if test "${want_chat}" = "true"; then
if test "${want_threads}" != "true"; then
AC_MSG_ERROR([--enable-chat requires multi-threading, use --enable-threads])
fi
LIBS="-L${LIBSTROPHE_LIB} ${default_LIBS}"
AC_CHECK_LIB([strophe], [xmpp_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libstrophe, use --with-libstrophe=PATH])], [-lexpat -lssl -lresolv])
AM_CONDITIONAL([WANT_CHAT], true)
AC_DEFINE([WANT_CHAT], 1, [enable Chat component])
# Check for Vysper
AC_CHECK_FILE([${VYSPER_PREFIX}/lib/vysper-core-0.5.jar], [want_vysper=true], [])
if test "${want_vysper}" = "true"; then
AM_CONDITIONAL([WANT_VYSPER], true)
else
AM_CONDITIONAL([WANT_VYSPER], false)
fi
else
AM_CONDITIONAL([WANT_CHAT], false)
AM_CONDITIONAL([WANT_VYSPER], false)
fi
# Configure GCC C++ and LD options.
AC_SUBST([CXXFLAGS], ["${cxxflags}"])
AC_SUBST([LDFLAGS], ["${ldflags}"])
LIBS="${defaultlibs}"
AC_CONFIG_FILES([Makefile
kernel/Makefile
modules/Makefile
modules/scheme/Makefile
modules/atom/Makefile
modules/json/Makefile
modules/scdl/Makefile
modules/http/Makefile
modules/python/Makefile
modules/java/Makefile
modules/server/Makefile
modules/wsgi/Makefile
components/Makefile
components/cache/Makefile
components/log/Makefile
components/chat/Makefile
components/queue/Makefile
components/sqldb/Makefile
components/store/Makefile
components/webservice/Makefile
samples/Makefile
test/Makefile
test/store-scheme/Makefile
test/store-cpp/Makefile
test/store-python/Makefile
test/store-java/Makefile
test/store-gae/Makefile
test/store-sql/Makefile
doc/Makefile
doc/Doxyfile
])
AC_OUTPUT

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
if WANT_DOXYGEN
BUILT_SOURCES = doxygen/index.html
doxygen/index.html: Doxyfile
doxygen
endif
datadir=$(prefix)/doc
clean:
rm -rf doxygen

View file

@ -0,0 +1,99 @@
# git-ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
# Generic ignores
target/
work/
tmp/
build/
*_build
.project
.cproject
.classpath
*.log
junit*.properties
surefire*.properties
.settings/
.deployables/
.wtpmodules/
.pydevproject
.buildpath
.svn/
.cvs/
.dotest/
*.la
*.lo
*.o
*.in
*.so
Makefile
.deps/
.libs/
m4/
*.m4
config.guess
config.sub
config.status
depcomp
install-sh
ltmain.sh
missing
stamp-h1
autom4te.cache/
deploy/
libtool
configure
config.h
Doxyfile
*.tar
*.tar.gz
*-bin/
*-src/
*_Proxy.cpp
*_Proxy.h
*_Wrapper.cpp
*_Wrapper.h
gmon.out
*~
tags
doxygen
*.pyc
*.class
*.stamp
*.jar
*.prefix
index.yaml
core
# Specific ignores
kernel-test
string-test
mem-test
hash-test
parallel-test
xml-test
xsd-test
atom-test
eval-test
eval-shell
json-test
client-test
memcache-test
curl-test
scdl-test
python-test
python-shell
jni-test
java-test
java-shell
script-test
axiom-test
axis2-test
qpid-test
xmpp-test
pgsql-test

View file

@ -0,0 +1,23 @@
#!/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.
# Remove ipcs created by httpd
ipcs -s | grep 0x | awk '{ print $2 }' | xargs -i -t ipcrm -s {}

View file

@ -0,0 +1,23 @@
#!/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.
# Run valgrind to analyze memory usage and track memory leaks
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes $* 2>&1 | tee memgrind.log

View file

@ -0,0 +1,136 @@
### This file configures various client-side behaviors.
###
### The commented-out examples below are intended to demonstrate
### how to use this file.
### Section for authentication and authorization customizations.
[auth]
### Set store-passwords to 'no' to avoid storing passwords in the
### auth/ area of your config directory. It defaults to 'yes'.
### Note that this option only prevents saving of *new* passwords;
### it doesn't invalidate existing passwords. (To do that, remove
### the cache files by hand as described in the Subversion book.)
# store-passwords = no
### Set store-auth-creds to 'no' to avoid storing any subversion
### credentials in the auth/ area of your config directory.
### It defaults to 'yes'. Note that this option only prevents
### saving of *new* credentials; it doesn't invalidate existing
### caches. (To do that, remove the cache files by hand.)
# store-auth-creds = no
### Section for configuring external helper applications.
[helpers]
### Set editor to the command used to invoke your text editor.
### This will override the environment variables that Subversion
### examines by default to find this information ($EDITOR,
### et al).
# editor-cmd = editor (vi, emacs, notepad, etc.)
### Set diff-cmd to the absolute path of your 'diff' program.
### This will override the compile-time default, which is to use
### Subversion's internal diff implementation.
# diff-cmd = diff_program (diff, gdiff, etc.)
### Set diff3-cmd to the absolute path of your 'diff3' program.
### This will override the compile-time default, which is to use
### Subversion's internal diff3 implementation.
# diff3-cmd = diff3_program (diff3, gdiff3, etc.)
### Set diff3-has-program-arg to 'true' or 'yes' if your 'diff3'
### program accepts the '--diff-program' option.
# diff3-has-program-arg = [true | false]
### Section for configuring tunnel agents.
[tunnels]
### Configure svn protocol tunnel schemes here. By default, only
### the 'ssh' scheme is defined. You can define other schemes to
### be used with 'svn+scheme://hostname/path' URLs. A scheme
### definition is simply a command, optionally prefixed by an
### environment variable name which can override the command if it
### is defined. The command (or environment variable) may contain
### arguments, using standard shell quoting for arguments with
### spaces. The command will be invoked as:
### <command> <hostname> svnserve -t
### (If the URL includes a username, then the hostname will be
### passed to the tunnel agent as <user>@<hostname>.) If the
### built-in ssh scheme were not predefined, it could be defined
### as:
# ssh = $SVN_SSH ssh
### If you wanted to define a new 'rsh' scheme, to be used with
### 'svn+rsh:' URLs, you could do so as follows:
# rsh = rsh
### Or, if you wanted to specify a full path and arguments:
# rsh = /path/to/rsh -l myusername
### On Windows, if you are specifying a full path to a command,
### use a forward slash (/) or a paired backslash (\\) as the
### path separator. A single backslash will be treated as an
### escape for the following character.
### Section for configuring miscelleneous Subversion options.
[miscellany]
### Set global-ignores to a set of whitespace-delimited globs
### which Subversion will ignore in its 'status' output.
# global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store
### Set log-encoding to the default encoding for log messages
# log-encoding = latin1
### Set use-commit-times to make checkout/update/switch/revert
### put last-committed timestamps on every file touched.
# use-commit-times = yes
### Set no-unlock to prevent 'svn commit' from automatically
### releasing locks on files.
# no-unlock = yes
### Set enable-auto-props to 'yes' to enable automatic properties
### for 'svn add' and 'svn import', it defaults to 'no'.
### Automatic properties are defined in the section 'auto-props'.
enable-auto-props = yes
### Section for configuring automatic properties.
[auto-props]
### The format of the entries is:
### file-name-pattern = propname[=value][;propname[=value]...]
### The file-name-pattern can contain wildcards (such as '*' and
### '?'). All entries which match will be applied to the file.
### Note that auto-props functionality must be enabled, which
### is typically done by setting the 'enable-auto-props' option.
# *.c = svn:eol-style=native
# *.cpp = svn:eol-style=native
# *.h = svn:eol-style=native
# *.dsp = svn:eol-style=CRLF
# *.dsw = svn:eol-style=CRLF
# *.sh = svn:eol-style=native;svn:executable
# *.txt = svn:eol-style=native
# *.png = svn:mime-type=image/png
# *.jpg = svn:mime-type=image/jpeg
# Makefile = svn:eol-style=native
*.c = svn:eol-style=native;svn:keywords=Rev Date
*.cpp = svn:eol-style=native;svn:keywords=Rev Date
*.h = svn:eol-style=native;svn:keywords=Rev Date
*.dsp = svn:eol-style=CRLF
*.dsw = svn:eol-style=CRLF
*.sh = svn:eol-style=native;svn:executable;svn:keywords=Rev Date
*.bat = svn:eol-style=native;svn:keywords=Rev Date
*.txt = svn:eol-style=native;svn:keywords=Rev Date
*.png = svn:mime-type=image/png
*.jpg = svn:mime-type=image/jpeg
*.am = svn:eol-style=native;svn:keywords=Rev Date
*.ac = svn:eol-style=native;svn:keywords=Rev Date
*.xml = svn:eol-style=native;svn:keywords=Rev Date
*.xsd = svn:eol-style=native;svn:keywords=Rev Date
*.html = svn:eol-style=native;svn:keywords=Rev Date
*.wsdl = svn:eol-style=native;svn:keywords=Rev Date
*.xsd = svn:eol-style=native;svn:keywords=Rev Date
*.composite = svn:eol-style=native;svn:keywords=Rev Date
*.componentType = svn:eol-style=native;svn:keywords=Rev Date
*.rb = svn:eol-style=native;svn:keywords=Rev Date
*.py = svn:eol-style=native;svn:keywords=Rev Date
*.php = svn:eol-style=native;svn:keywords=Rev Date
*.js = svn:eol-style=native;svn:keywords=Rev Date
*.java = svn:eol-style=native;svn:keywords=Rev Date
*.properties = svn:eol-style=native;svn:keywords=Rev Date
*.jelly = svn:eol-style=native;svn:keywords=Rev Date
*.ipr = svn:eol-style=native
*.iml = svn:eol-style=native
*.project = svn:eol-style=native
*.classpath = svn:eol-style=native
README = svn:eol-style=native;svn:keywords=Rev Date
LICENSE = svn:eol-style=native
NOTICE = svn:eol-style=native

View file

@ -0,0 +1,55 @@
configure
Makefile.in
depcomp
config.guess
config.h
config.sub
ltmain.sh
Makefile
config.status
stamp-h1
config.h.in
libtool
autom4te.cache
missing
aclocal.m4
install-sh
.deps
*.dat
.libs
tmp
build
.project
.cdtproject
.settings
*_Proxy.cpp
*_Proxy.h
*_Wrapper.cpp
*_Wrapper.h
.pydevproject
.buildpath
*.lib
*.dll
*.exe
*.suo
*.ncb
*.user
*.pdb
Debug
Release
gmon.out
m4
*.tar.gz
*.pyc
*.log
*-bin
*-src
Doxyfile
*~
tags
doxygen
*.stamp
*.class
*.jar
*.prefix
target

View file

@ -0,0 +1,45 @@
# 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.
includedir = $(prefix)/include/kernel
include_HEADERS = *.hpp
string_test_SOURCES = string-test.cpp
test_LTLIBRARIES = libdynlib-test.la
testdir = $(prefix)/test
libdynlib_test_la_SOURCES = dynlib-test.cpp
kernel_test_SOURCES = kernel-test.cpp
mem_test_SOURCES = mem-test.cpp
parallel_test_SOURCES = parallel-test.cpp
xml_test_SOURCES = xml-test.cpp
xml_test_LDFLAGS = -lxml2
xsd_test_SOURCES = xsd-test.cpp
xsd_test_LDFLAGS = -lxml2
hash_test_SOURCES = hash-test.cpp
noinst_PROGRAMS = string-test kernel-test hash-test mem-test parallel-test xml-test xsd-test
TESTS = string-test kernel-test hash-test mem-test parallel-test xml-test

View file

@ -0,0 +1,76 @@
/*
* 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$ */
#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"
/**
* Platform configuration and debug functions.
*/
namespace tuscany
{
#ifdef WANT_MAINTAINER_MODE
/**
* Add string watch members to important classes to help watch them in a debugger.
*/
#define WANT_MAINTAINER_WATCH
/**
* Increment / decrement a debug counter.
*/
bool debug_inc(long int& c) {
c++;
return true;
}
bool debug_dec(long int& c) {
c--;
return true;
}
#else
#define debug_inc(c)
#define debug_dec(c)
#endif
/**
* Attribute used to mark unused parameters.
*/
#ifndef unused
#define unused __attribute__ ((unused))
#endif
}
#endif /* tuscany_config_hpp */

View file

@ -0,0 +1,48 @@
/*
* 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 library.
*/
#include "function.hpp"
namespace tuscany {
namespace test {
const int cppsquare(int x) {
return x * x;
}
}
}
extern "C" {
const int csquare(const int x) {
return tuscany::test::cppsquare(x);
}
const tuscany::lambda<int(const int)> csquarel() {
return tuscany::lambda<int(const int)>(tuscany::test::cppsquare);
}
}

View file

@ -0,0 +1,91 @@
/*
* 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$ */
#ifndef tuscany_dlib_hpp
#define tuscany_dlib_hpp
/**
* Simple dynamic library access functions.
*/
#include <dlfcn.h>
#include "function.hpp"
#include "gc.hpp"
#include "monad.hpp"
namespace tuscany {
/**
* OS specific dynamic library file extension.
*/
#ifdef IS_DARWIN
const string dynlibExt(".dylib");
#else
const string dynlibExt(".so");
#endif
/**
* Represents a reference to a dynamic library.
*/
class lib {
public:
lib() : h(NULL), owner(false) {
}
lib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)), owner(true) {
if (h == NULL)
h = mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror());
}
lib(const lib& l) : name(l.name), h(l.h), owner(false) {
}
~lib() {
if (!owner)
return;
if (!hasContent(h) || content(h) == NULL)
return;
dlclose(content(h));
}
private:
template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l);
const string name;
failable<void*> h;
bool owner;
};
/**
* Find a lambda function in a dynamic library.
*/
template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) {
if (!hasContent(l.h))
return mkfailure<lambda<S> >(reason(l.h));
const void* s = dlsym(content(l.h), c_str(name));
if (s == NULL)
return mkfailure<lambda<S> >(string("Could not load symbol: ") + name);
return lambda<S>((S*)s);
}
}
#endif /* tuscany_dlib_hpp */

View file

@ -0,0 +1,304 @@
/*
* 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$ */
#ifndef tuscany_element_hpp
#define tuscany_element_hpp
/**
* Functions to help represent data as lists of elements and attributes.
*/
#include "list.hpp"
#include "value.hpp"
namespace tuscany
{
/**
* Tags used to tag lists of elements and attributes.
*/
const value attribute("attribute");
const value element("element");
const string atsign("@");
/**
* Returns true if a value is an element.
*/
bool isElement(const value& v) {
if (!isList(v) || isNil(v) || element != car<value>(v))
return false;
return true;
}
/**
* Returns true if a value is an attribute.
*/
bool isAttribute(const value& v) {
if (!isList(v) || isNil(v) || attribute != car<value>(v))
return false;
return true;
}
/**
* Returns the name of an attribute.
*/
const value attributeName(const list<value>& l) {
return cadr(l);
}
/**
* Returns the value of an attribute.
*/
const value attributeValue(const list<value>& l) {
return caddr(l);
}
/**
* Returns the name of an element.
*/
const value elementName(const list<value>& l) {
return cadr(l);
}
/**
* Returns true if an element has children.
*/
const bool elementHasChildren(const list<value>& l) {
return !isNil(cddr(l));
}
/**
* Returns the children of an element.
*/
const list<value> elementChildren(const list<value>& l) {
return cddr(l);
}
/**
* Returns true if an element has a value.
*/
const value elementHasValue(const list<value>& l) {
const list<value> r = reverse(l);
if (isSymbol(car(r)))
return false;
if(isList(car(r)) && !isNil((list<value>)car(r)) && isSymbol(car<value>(car(r))))
return false;
return true;
}
/**
* Returns the value of an element.
*/
const value elementValue(const list<value>& l) {
return car(reverse(l));
}
/**
* Convert an element to a value.
*/
const bool elementToValueIsList(const value& v) {
if (!isList(v))
return false;
const list<value> l = v;
return (isNil(l) || !isSymbol(car(l)));
}
const value elementToValue(const value& t) {
const list<value> elementsToValues(const list<value>& e);
// Convert an attribute
if (isTaggedList(t, attribute))
return mklist<value>(c_str(atsign + attributeName(t)), attributeValue(t));
// Convert an element
if (isTaggedList(t, element)) {
// Convert an element's value
if (elementHasValue(t)) {
// Convert a single value
if (!elementToValueIsList(elementValue(t)))
return mklist(elementName(t), elementValue(t));
// Convert a list value
return cons(elementName(t), mklist<value>(elementsToValues(elementValue(t))));
}
// Convert an element's children
return cons(elementName(t), elementsToValues(elementChildren(t)));
}
// Convert a value
if (!isList(t))
return t;
return elementsToValues(t);
}
/**
* Convert a list of elements to a list of values.
*/
const bool elementToValueIsSymbol(const value& v) {
if (!isList(v))
return false;
const list<value> l = v;
if (isNil(l))
return false;
if (!isSymbol(car(l)))
return false;
return true;
}
const list<value> elementToValueGroupValues(const value& v, const list<value>& l) {
if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l)))
return cons(v, l);
if (car<value>(car(l)) != car<value>(v))
return cons(v, l);
if (!elementToValueIsList(cadr<value>(car(l)))) {
const value g = mklist<value>(car<value>(v), mklist<value>(cdr<value>(v), cdr<value>(car(l))));
return elementToValueGroupValues(g, cdr(l));
}
const value g = mklist<value>(car<value>(v), cons<value>(cdr<value>(v), (list<value>)cadr<value>(car(l))));
return elementToValueGroupValues(g, cdr(l));
}
const list<value> elementsToValues(const list<value>& e) {
if (isNil(e))
return e;
return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e)));
}
/**
* Convert a value to an element.
*/
const value valueToElement(const value& t) {
const list<value> valuesToElements(const list<value>& l);
// Convert a name value pair
if (isList(t) && !isNil((list<value>)t) && isSymbol(car<value>(t))) {
const value n = car<value>(t);
const value v = cadr<value>(t);
// Convert a single value to an attribute or an element
if (!isList(v)) {
if (substr(n, 0, 1) == atsign)
return mklist<value>(attribute, substr(n, 1), v);
return mklist(element, n, v);
}
// Convert a list value
if (isNil((list<value>)v) || !isSymbol(car<value>(v)))
return cons(element, cons(n, mklist<value>(valuesToElements(v))));
// Convert a nested name value pair value
return cons(element, cons(n, valuesToElements(cdr<value>(t))));
}
// Convert a value
if (!isList(t))
return t;
return valuesToElements(t);
}
/**
* Convert a list of values to a list of elements.
*/
const list<value> valuesToElements(const list<value>& l) {
if (isNil(l))
return l;
return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l)));
}
/**
* Returns a selector lambda function which can be used to filter
* elements against the given element pattern.
*/
struct selectorLambda {
const list<value> select;
selectorLambda(const list<value>& s) : select(s) {
}
const bool evalSelect(const list<value>& s, const list<value> v) const {
if (isNil(s))
return true;
if (isNil(v))
return false;
if (car(s) != car(v))
return false;
return evalSelect(cdr(s), cdr(v));
}
const bool operator()(const value& v) const {
if (!isList(v))
return false;
return evalSelect(select, v);
}
};
const lambda<bool(const value&)> selector(const list<value> s) {
return selectorLambda(s);
}
/**
* Returns the value of the attribute with the given name.
*/
struct filterAttribute {
const value name;
filterAttribute(const value& n) : name(n) {
}
const bool operator()(const value& v) const {
return isAttribute(v) && attributeName((list<value>)v) == name;
}
};
const value attributeValue(const value& name, const value& l) {
const list<value> f = filter<value>(filterAttribute(name), list<value>(l));
if (isNil(f))
return value();
return caddr<value>(car(f));
}
/**
* Returns child elements with the given name.
*/
struct filterElement {
const value name;
filterElement(const value& n) : name(n) {
}
const bool operator()(const value& v) const {
return isElement(v) && elementName((list<value>)v) == name;
}
};
const value elementChildren(const value& name, const value& l) {
return filter<value>(filterElement(name), list<value>(l));
}
/**
* Return the child element with the given name.
*/
const value elementChild(const value& name, const value& l) {
const list<value> f = elementChildren(name, l);
if (isNil(f))
return value();
return car(f);
}
}
#endif /* tuscany_element_hpp */

View file

@ -0,0 +1,162 @@
/*
* 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$ */
#ifndef tuscany_fstream_hpp
#define tuscany_fstream_hpp
/**
* File based streams.
*/
#include <stdio.h>
#include <stdarg.h>
#include "string.hpp"
#include "stream.hpp"
namespace tuscany {
/*
* Output stream backed by a FILE.
*/
class ofstream : public ostream {
public:
ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) {
}
ofstream(FILE* file) : file(file), owner(false) {
}
ofstream(const ofstream& os) : file(os.file), owner(false) {
}
~ofstream() {
if (!owner)
return;
if (file == NULL)
return;
fclose(file);
}
ofstream& vprintf(const char* fmt, ...) {
va_list args;
va_start (args, fmt);
vfprintf (file, fmt, args);
va_end (args);
return *this;
}
ofstream& write(const string& s) {
fwrite(c_str(s), 1, length(s), file);
return *this;
}
ofstream& flush() {
fflush(file);
return *this;
}
private:
FILE* file;
bool owner;
};
/*
* Input stream backed by a FILE.
*/
class ifstream : public istream {
public:
ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) {
}
ifstream(FILE* file) : file(file), owner(false) {
}
ifstream(const ifstream& is) : file(is.file), owner(false) {
}
~ifstream() {
if (!owner)
return;
if (file == NULL)
return;
fclose(file);
}
const int read(void* buf, int size) {
return fread(buf, 1, size, file);
}
const bool eof() {
return feof(file);
}
const bool fail() {
return file == NULL;
}
const int get() {
return fgetc(file);
}
const int peek() {
int c = fgetc(file);
if (c == -1)
return c;
ungetc(c, file);
return c;
}
private:
FILE* file;
bool owner;
};
/**
* Standard streams.
*/
ofstream cout(stdout);
ofstream cerr(stderr);
ifstream cin(stdin);
/**
* Debug log stream.
*/
#ifdef WANT_MAINTAINER_MODE
template<typename V> const bool debug(const V& v, const string& msg) {
cerr << msg << ": " << v << endl;
return true;
}
const bool debug(const string& msg) {
cerr << msg << endl;
return true;
}
#else
#define debug(...)
#endif
}
#endif /* tuscany_fstream_hpp */

View file

@ -0,0 +1,238 @@
/*
* 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$ */
#ifndef tuscany_function_hpp
#define tuscany_function_hpp
/**
* Lambda function type.
*/
#include <utility>
#include "fstream.hpp"
#include "gc.hpp"
#include "config.hpp"
namespace tuscany {
#ifdef WANT_MAINTAINER_MODE
/**
* Debug counters.
*/
long int countProxies;
long int countFProxies = 0;
long int countCProxies = 0;
long int countLambdas = 0;
long int countELambdas = 0;
long int countCLambdas = 0;
long int countFLambdas = 0;
bool resetLambdaCounters() {
countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0;
return true;
}
bool checkLambdaCounters() {
return countLambdas == 0;
}
bool printLambdaCounters() {
cout << "countLambdas " << countLambdas << endl;
cout << "countELambdas " << countELambdas << endl;
cout << "countFLambdas " << countFLambdas << endl;
cout << "countCLambdas " << countCLambdas << endl;
cout << "countProxies " << countProxies << endl;
cout << "countFProxies " << countFProxies << endl;
cout << "countCProxies " << countCProxies << endl;
return true;
}
#else
#define resetLambdaCounters()
#define checkLambdaCounters() true
#define printLambdaCounters()
#endif
/**
* Lambda function type.
*/
template<typename R, typename... P> class Callable {
public:
Callable() {
}
virtual const int size() const = 0;
virtual const R operator()(P... p) const = 0;
virtual ~Callable() {
}
template<typename F> class Proxy: public Callable {
public:
Proxy(const F& f) : function(f) {
debug_inc(countProxies);
debug_inc(countFProxies);
}
Proxy(const Proxy& p) : function(p.function) {
debug_inc(countProxies);
debug_inc(countCProxies);
}
~Proxy() {
debug_dec(countProxies);
}
virtual const R operator() (P... p) const {
return function(std::forward<P>(p)...);
}
virtual const int size() const {
return sizeof(function);
}
private:
const F function;
};
};
template<typename S> class lambda;
template<typename R, typename... P> class lambda<R(P...)> {
public:
lambda() : callable(0) {
debug_inc(countLambdas);
debug_inc(countELambdas);
}
template<typename F> lambda(const F f) {
debug_inc(countLambdas);
debug_inc(countFLambdas);
typedef typename CallableType::template Proxy<F> ProxyType;
callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
}
lambda(const lambda& l) {
debug_inc(countLambdas);
debug_inc(countCLambdas);
callable = l.callable;
}
const lambda& operator=(const lambda& l) {
if (this == &l)
return *this;
callable = l.callable;
return *this;
}
~lambda() {
debug_dec(countLambdas);
}
const bool operator==(const lambda& l) const {
if (this == &l)
return true;
return callable == l.callable;
}
const bool operator!=(const lambda& l) const {
return !this->operator==(l);
}
const R operator()(P... p) const {
return (*callable)(std::forward<P>(p)...);
}
template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&);
template<typename S> friend const bool isNil(const lambda<S>& l);
private:
typedef Callable<R,P...> CallableType;
gc_ptr<CallableType> callable;
};
template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) {
return out << "lambda::" << l.callable;
}
/**
* Return true if a lambda is nil.
*/
template<typename S> const bool isNil(const lambda<S>& l) {
return ((void*)l.callable) == 0;
}
/**
* Curry a lambda function.
*/
template<typename R, typename T, typename... P> class curried {
public:
curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) {
}
const R operator()(P... p) const {
return f(v, std::forward<P>(p)...);
}
private:
const T v;
const lambda<R(T, P...)>f;
};
template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) {
return curried<R, T, P...>(f, t);
}
template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) {
return curry(curry(f, t), u);
}
template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) {
return curry(curry(curry(f, t), u), v);
}
/**
* A lambda function that returns the given value.
*/
template<typename T> class returnResult {
public:
returnResult(const T& v) :
v(v) {
}
const T operator()() const {
return v;
}
private:
const T v;
};
template<typename T> const lambda<T()> result(const T& v) {
return returnResult<T> (v);
}
}
#endif /* tuscany_function_hpp */

View file

@ -0,0 +1,276 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_gc_hpp
#define tuscany_gc_hpp
/**
* Garbage collected memory management, using APR memory pools.
*/
#include <stdlib.h>
#include <apr_general.h>
#include <apr_pools.h>
#include <assert.h>
#include <new>
#include "config.hpp"
namespace tuscany
{
/**
* Pointer to a value.
*/
template<typename T> class gc_ptr {
public:
gc_ptr(T* ptr = NULL) throw() : ptr(ptr) {
}
~gc_ptr() throw() {
}
gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) {
}
gc_ptr& operator=(const gc_ptr& r) throw() {
if(this == &r)
return *this;
ptr = r.ptr;
return *this;
}
const bool operator==(const gc_ptr& r) const throw() {
if (this == &r)
return true;
return ptr == r.ptr;
}
const bool operator!=(const gc_ptr& r) const throw() {
return !this->operator==(r);
}
T& operator*() const throw() {
return *ptr;
}
T* operator->() const throw() {
return ptr;
}
operator T*() const throw() {
return ptr;
}
T* ptr;
};
/**
* Garbage collected APR memory pool.
*/
class gc_pool {
public:
gc_pool() : apr_pool(NULL) {
}
gc_pool(apr_pool_t* p) : apr_pool(p) {
}
gc_pool(const gc_pool& pool) : apr_pool(pool.apr_pool) {
}
gc_pool& operator=(const gc_pool& pool) {
if (this == &pool)
return *this;
apr_pool = pool.apr_pool;
return *this;
}
private:
friend apr_pool_t* pool(const gc_pool& pool);
friend class gc_global_pool_t;
friend class gc_scoped_pool;
apr_pool_t* apr_pool;
};
/**
* Return APR pool used by a gc_pool.
*/
apr_pool_t* pool(const gc_pool& pool) {
return pool.apr_pool;
}
/**
* Destroy a memory pool.
*/
const bool destroy(const gc_pool& p) {
apr_pool_destroy(pool(p));
return true;
}
/**
* Initialize APR.
*/
class gc_apr_context_t {
public:
gc_apr_context_t() {
apr_initialize();
}
} gc_apr_context;
/**
* Maintain a stack of memory pools.
*/
#ifdef WANT_THREADS
__thread
#endif
apr_pool_t* gc_pool_stack = NULL;
/**
* Return the current memory pool.
*/
apr_pool_t* gc_current_pool() {
apr_pool_t* apr_pool = gc_pool_stack;
if (apr_pool != NULL)
return apr_pool;
// Create a parent pool for the current thread
apr_pool_create(&apr_pool, NULL);
assert(apr_pool != NULL);
gc_pool_stack = apr_pool;
return apr_pool;
}
/**
* Push a pool onto the stack.
*/
apr_pool_t* gc_push_pool(apr_pool_t* pool) {
apr_pool_t* p = gc_pool_stack;
gc_pool_stack = pool;
return p;
}
/**
* Pop a pool from the stack.
*/
apr_pool_t* gc_pop_pool(apr_pool_t* pool) {
apr_pool_t* p = gc_pool_stack;
gc_pool_stack = pool;
return p;
}
/**
* A memory pool scope, used to setup a scope in which a particular pool
* will be used for all allocations.
*/
class gc_scoped_pool : public gc_pool {
public:
gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owner(true) {
apr_pool_create(&apr_pool, NULL);
assert(apr_pool != NULL);
gc_push_pool(apr_pool);
}
gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owner(false) {
gc_push_pool(apr_pool);
}
~gc_scoped_pool() {
if (owner)
apr_pool_destroy(apr_pool);
gc_pop_pool(prev);
}
private:
gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.apr_pool), prev(NULL), owner(false) {
}
apr_pool_t* prev;
bool owner;
};
/**
* Allocates a pointer to an object allocated from a memory pool and
* register a cleanup callback for it.
*/
template<typename T> apr_status_t gc_pool_cleanup(void* v) {
T* t = static_cast<T*>(v);
t->~T();
return APR_SUCCESS;
}
template<typename T> T* gc_new(apr_pool_t* p) {
void* gc_new_ptr = apr_palloc(p, sizeof(T));
assert(gc_new_ptr != NULL);
apr_pool_cleanup_register(p, gc_new_ptr, gc_pool_cleanup<T>, apr_pool_cleanup_null) ;
return static_cast<T*>(gc_new_ptr);
}
template<typename T> T* gc_new(const gc_pool& p) {
return gc_new<T>(pool(p));
}
template<typename T> T* gc_new() {
return gc_new<T>(gc_current_pool());
}
template<typename T> apr_status_t gc_pool_acleanup(void* v) {
int* m = static_cast<int*>(v);
int n = *m;
T* t = (T*)(m + 1);
for (int i = 0; i < n; i++, t++)
t->~T();
return APR_SUCCESS;
}
template<typename T> T* gc_anew(apr_pool_t* p, int n) {
int* gc_anew_ptr = static_cast<int*>(apr_palloc(p, sizeof(int) + sizeof(T[n])));
assert(gc_anew_ptr != NULL);
*gc_anew_ptr = n;
apr_pool_cleanup_register(p, gc_anew_ptr, gc_pool_acleanup<T>, apr_pool_cleanup_null) ;
return (T*)(gc_anew_ptr + 1);
}
template<typename T> T* gc_anew(const gc_pool& p, int n) {
return gc_anew<T>(pool(p), n);
}
template<typename T> T* gc_anew(int n) {
return gc_anew<T>(gc_current_pool(), n);
}
/**
* Allocate an array of chars.
*/
char* gc_cnew(apr_pool_t* p, int n) {
char* gc_cnew_ptr = static_cast<char*>(apr_palloc(p, n));
assert(gc_cnew_ptr != NULL);
return gc_cnew_ptr;
}
char* gc_cnew(int n) {
return gc_cnew(gc_current_pool(), n);
}
}
#endif /* tuscany_gc_hpp */

View file

@ -0,0 +1,135 @@
/*
* 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 hash functions.
*/
#include <assert.h>
#include "string.hpp"
#include "hash.hpp"
#include "perf.hpp"
namespace tuscany {
bool testCrc32hash() {
const string key("This is a test key");
unsigned int h = crc32hash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testTimes33hash() {
const string key("This is a test key");
unsigned int h = times33hash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testMurmurhash() {
const string key("This is a test key");
unsigned int h = murmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testPortablemurmurhash() {
const string key("This is a test key");
unsigned int h = portablemurmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
struct crc32hashTest {
const string key;
crc32hashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = crc32hash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct times33hashTest {
const string key;
times33hashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = times33hash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct murmurhashTest {
const string key;
murmurhashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = murmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct portablemurmurhashTest {
const string key;
portablemurmurhashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = portablemurmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
bool testHashPerf() {
const string key("This is a test key");
const int count = 100000;
const lambda<bool()> crc32 = crc32hashTest(key);
cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl;
const lambda<bool()> times33 = times33hashTest(key);
cout << "times33hash test " << time(times33, 5, count) << " ms" << endl;
const lambda<bool()> murmur = murmurhashTest(key);
cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl;
const lambda<bool()> portablemurmur = portablemurmurhashTest(key);
cout << "portable murmurhash test " << time(portablemurmur, 5, count) << " ms" << endl;
return true;
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testCrc32hash();
tuscany::testTimes33hash();
tuscany::testMurmurhash();
tuscany::testPortablemurmurhash();
tuscany::testHashPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,207 @@
/*
* 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$ */
#ifndef tuscany_hash_hpp
#define tuscany_hash_hpp
/**
* Fast hash functions.
*/
#include <apr_hash.h>
#include <apr_memcache.h>
namespace tuscany
{
/**
* Apache apr-util CRC32 hash function.
*
* See srclib/apr-util/memcache/apr_memcache.c from the Apache HTTPD
* source tree. Reproducing the comments from apr_memcache.c here:
*
* The crc32 functions and data were originally written by Spencer
* Garrett <srg@quick.com> and were gleaned from the PostgreSQL source
* tree at contrib/ltree/crc32.[ch] and from FreeBSD at
* src/usr.bin/cksum/crc32.c.
*/
const unsigned int crc32hash(const char* data, const unsigned int len) {
return apr_memcache_hash_default(NULL, data, len);
}
/**
* Apache apr tables default hash function.
*
* See srclib/apr/tables/apr_hash.c from the Apache HTTPD source tree.
* Reproducing the comments from apr_hash.c here:
*
* This is the popular `times 33' hash algorithm which is used by
* perl and also appears in Berkeley DB. This is one of the best
* known hash functions for strings because it is both computed
* very fast and distributes very well.
*
* The originator may be Dan Bernstein but the code in Berkeley DB
* cites Chris Torek as the source. The best citation I have found
* is "Chris Torek, Hash function for text in C, Usenet message
* <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
* Salz's USENIX 1992 paper about INN which can be found at
* <http://citeseer.nj.nec.com/salz92internetnews.html>.
*
* The magic of number 33, i.e. why it works better than many other
* constants, prime or not, has never been adequately explained by
* anyone. So I try an explanation: if one experimentally tests all
* multipliers between 1 and 256 (as I did while writing a low-level
* data structure library some time ago) one detects that even
* numbers are not useable at all. The remaining 128 odd numbers
* (except for the number 1) work more or less all equally well.
* They all distribute in an acceptable way and this way fill a hash
* table with an average percent of approx. 86%.
*
* If one compares the chi^2 values of the variants (see
* Bob Jenkins ``Hashing Frequently Asked Questions'' at
* http://burtleburtle.net/bob/hash/hashfaq.html for a description
* of chi^2), the number 33 not even has the best value. But the
* number 33 and a few other equally good numbers like 17, 31, 63,
* 127 and 129 have nevertheless a great advantage to the remaining
* numbers in the large set of possible multipliers: their multiply
* operation can be replaced by a faster operation based on just one
* shift plus either a single addition or subtraction operation. And
* because a hash function has to both distribute good _and_ has to
* be very fast to compute, those few numbers should be preferred.
*
* -- Ralf S. Engelschall <rse@engelschall.com>
*/
const unsigned int times33hash(const char* data, const unsigned int len) {
apr_ssize_t l = len;
return apr_hashfunc_default(data, &l);
}
/**
* A very fast, non-cryptographic hash suitable for general hash-based
* lookup. See http://murmurhash.googlepages.com/ for more details.
*
* Original code by Austin Appleby, released to the public domain and under
* the MIT license.
*
* Compiles down to ~52 instructions on x86.
* Passes chi^2 tests for practically all keysets & bucket sizes.
* Excellent avalanche behavior. Maximum bias is under 0.5%.
* Passes Bob Jenkin's frog.c torture-test. No collisions possible for 4 byte
* keys, no small 1 to 7 bit differentials.
*/
const unsigned int murmurhash(const char* key, const unsigned int klen) {
unsigned int len = klen;
const unsigned int seed = 0;
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const unsigned int m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
unsigned int h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char* data = (const unsigned char*)key;
while(len >= 4) {
unsigned int k = *(unsigned int*)data;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len) {
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
/**
* An endian and alignment neutral, but half the speed, version of
* the murmur hash.
*/
const unsigned int portablemurmurhash(const char* key, const unsigned int klen) {
unsigned int len = klen;
const unsigned int seed = 0;
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const unsigned int m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
unsigned int h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char* data = (const unsigned char *)key;
while(len >= 4) {
unsigned int k;
k = data[0];
k |= data[1] << 8;
k |= data[2] << 16;
k |= data[3] << 24;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len) {
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
const unsigned int hashselect(const unsigned int hash, const unsigned int max) {
return hash % max;
}
}
#endif /* tuscany_hash_hpp */

View file

@ -0,0 +1,594 @@
/*
* 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 kernel functions.
*/
#include <assert.h>
#include "string.hpp"
#include "sstream.hpp"
#include "function.hpp"
#include "list.hpp"
#include "tree.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "dynlib.hpp"
#include "perf.hpp"
namespace tuscany {
struct inc {
int i;
inc(int i) :
i(i) {
}
const int operator()(const int x) const {
return x + i;
}
};
const int square(const int x) {
return x * x;
}
int mapLambda(lambda<int(const int)> f, int v) {
return f(v);
}
bool testLambda() {
const lambda<int(const int)> sq(square);
assert(sq(2) == 4);
assert(mapLambda(sq, 2) == 4);
assert(mapLambda(square, 2) == 4);
const lambda<int(const int)> incf(inc(10));
assert(incf(1) == 11);
assert(mapLambda(incf, 1) == 11);
assert(mapLambda(inc(10), 1) == 11);
lambda<int(const int)> l;
l = incf;
assert(l(1) == 11);
l = square;
assert(l(2) == 4);
return true;
}
bool testLambdaGC() {
resetLambdaCounters();
{
gc_scoped_pool gc;
testLambda();
}
assert(checkLambdaCounters());
return true;
}
int countElements = 0;
struct Element {
int i;
Element() : i(0) {
countElements++;
}
Element(int i) : i(i) {
countElements++;
}
Element(const Element& o) : i(o.i) {
countElements++;
}
~Element() {
countElements--;
}
const bool operator==(const Element& o) const {
return o.i == i;
}
};
ostream& operator<<(ostream& out, const Element& v) {
out << v.i ;
return out;
}
bool testCons() {
assert(car(cons(2, mklist(3))) == 2);
assert(car(cdr(cons(2, mklist(3)))) == 3);
assert(isNil(cdr(cdr(cons(2, mklist(3))))));
assert(cons(Element(1), mklist(Element(2))) == mklist(Element(1), Element(2)));
return true;
}
bool testListGC() {
resetLambdaCounters();
resetListCounters();
countElements = 0;
{
gc_scoped_pool gc;
testCons();
}
assert(checkLambdaCounters());
assert(checkListCounters());
assert(countElements == 0);
return true;
}
bool testOut() {
ostringstream os1;
os1 << list<int> ();
assert(str(os1) == "()");
ostringstream os2;
os2 << mklist(1, 2, 3);
assert(str(os2) == "(1 2 3)");
return true;
}
bool testEquals() {
assert(list<int>() == list<int>());
assert(mklist(1, 2) == mklist(1, 2));
assert(list<int>() != mklist(1, 2));
assert(mklist(1, 2, 3) == mklist(1, 2, 3));
assert(mklist(1, 2) != mklist(1, 2, 3));
return true;
}
bool testLength() {
assert(0 == length(list<int>()));
assert(1 == length(mklist(1)));
assert(2 == length(cons(1, mklist(2))));
return true;
}
bool testAppend() {
assert(car(append(mklist(1), mklist(2))) == 1);
assert(car(cdr(append(mklist(1), mklist(2)))) == 2);
assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3);
assert(isNil(cdr(cdr(cdr(append(mklist(1), mklist(2, 3)))))));
assert(list<int>() + 1 + 2 + 3 == mklist(1, 2, 3));
return true;
}
struct Complex {
int x;
int y;
Complex() {
}
Complex(int x, int y) :
x(x), y(y) {
}
};
ostream& operator<<(ostream& out, const Complex& v) {
out << "[" << v.x << ":" << v.y << "]";
return out;
}
bool testComplex() {
const list<Complex> p = mklist(Complex(1, 2), Complex(3, 4));
assert(car(p).x == 1);
assert(car(cdr(p)).x == 3);
assert(isNil(cdr(cdr(p))));
return true;
}
bool testMap() {
assert(isNil(map<int, int>(square, list<int>())));
const list<int> m = map<int, int>(square, mklist(2, 3));
assert(car(m) == 4);
assert(car(cdr(m)) == 9);
return true;
}
const int add(const int x, const int y) {
return x + y;
}
bool testReduce() {
const lambda<int(const int, const int)> r(add);
assert(reduce(r, 0, mklist(1, 2, 3)) == 6);
return true;
}
bool isPositive(const int x) {
if(x >= 0)
return true;
else
return false;
}
bool testFilter() {
assert(car(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 1);
assert(cadr(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 2);
return true;
}
bool testMember() {
assert(isNil(member(4, mklist(1, 2, 3))));
assert(car(member(1, mklist(1, 2, 3))) == 1);
assert(car(member(2, mklist(1, 2, 3))) == 2);
assert(car(member(3, mklist(1, 2, 3))) == 3);
return true;
}
bool testReverse() {
assert(isNil(reverse(list<int>())));
assert(car(reverse(mklist(1, 2, 3))) == 3);
assert(cadr(reverse(mklist(1, 2, 3))) == 2);
return true;
}
bool testListRef() {
assert(listRef(mklist(1), 0) == 1);
assert(listRef(mklist(1, 2, 3), 0) == 1);
assert(listRef(mklist(1, 2, 3), 1) == 2);
assert(listRef(mklist(1, 2, 3), 2) == 3);
return true;
}
bool testAssoc() {
const list<list<string> > l = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA"));
assert(assoc<string>("a", l) == mklist<string>("a", "A"));
assert(isNil(assoc<string>("z", l)));
const list<list<value> > u = mklist(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
assert(assoc<value>("a", u) == mklist<value>("a", "A"));
const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
assert(assoc<value>("a", v) == mklist<value>("a", "A"));
return true;
}
bool testZip() {
const list<string> k = mklist<string>("x", "a", "y", "a");
const list<string> v = mklist<string>("X", "A", "Y", "AA");
const list<list<string> > z = mklist(k, v);
const list<list<string> > u = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA"));
assert(zip(k, v) == u);
assert(unzip(u) == z);
return true;
}
bool testTokenize() {
assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd"));
assert(tokenize("/", "/bbb/ccc/ddd") == mklist<string>("", "bbb", "ccc", "ddd"));
assert(tokenize("/", "/bbb/ccc/") == mklist<string>("", "bbb", "ccc"));
assert(tokenize("/", "/bbb//ccc/") == mklist<string>("", "bbb", "", "ccc"));
assert(tokenize("/", "abc/def/") == mklist<string>("abc", "def"));
return true;
}
double testSeqMap(double x) {
return x;
}
double testSeqReduce(unused double v, double accum) {
return accum + 1.0;
}
bool testSeq() {
resetLambdaCounters();
resetListCounters();
list<double> s = seq(0.0, 1000.0);
assert(1001 == length(s));
assert(1001 == length(map<double, double>(testSeqMap, s)));
assert(801 == length(member(200.0, s)));
assert(201 == length(member(200.0, reverse(s))));
assert(1001 == (reduce<double, double>(testSeqReduce, 0.0, s)));
return true;
}
value valueSquare(list<value> x) {
return (int)car(x) * (int)car(x);
}
bool testValue() {
assert(value(true) == value(true));
assert(value(1) == value(1));
assert(value("abcd") == value("abcd"));
lambda<value(const list<value>&)> vl(valueSquare);
assert(value(vl) == value(vl));
assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2)));
const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"));
assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A"));
const value pv(gc_ptr<value>(new (gc_new<value>()) value(1)));
assert(*(gc_ptr<value>)pv == value(1));
const list<value> lpv = mklist<value>(gc_ptr<value>(new (gc_new<value>()) value(1)), gc_ptr<value>(new (gc_new<value>()) value(2)));
assert(*(gc_ptr<value>)car(lpv) == value(1));
return true;
}
bool testValueGC() {
resetLambdaCounters();
resetListCounters();
resetValueCounters();
{
gc_scoped_pool gc;
testValue();
}
assert(checkValueCounters());
assert(checkLambdaCounters());
assert(checkListCounters());
return true;
}
bool testTree() {
const list<value> t = mktree<value>("a", list<value>(), list<value>());
const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t)))));
const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a"));
assert(mt == ct);
const list<value> l = flatten<value>(mt);
assert(length(l) == 6);
assert(car(l) == "a");
assert(car(reverse(l)) == "f");
const list<value> bt = mkbtree<value>(l);
assert(car(bt) == "c");
return true;
}
const list<value> lta(const string& x) {
return mklist<value>(c_str(x), c_str(x + x));
}
bool testTreeAssoc() {
const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>());
const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t)))));
const list<value> l = flatten<value>(at);
assert(length(l) == 6);
assert(car(l) == mklist<value>("a", "aa"));
assert(car(reverse(l)) == mklist<value>("f", "ff"));
const list<value> bt = mkbtree<value>(l);
assert(car(bt) == mklist<value>("c", "cc"));
assert(assoctree<value>("a", bt) == mklist<value>("a", "aa"));
assert(assoctree<value>("b", bt) == mklist<value>("b", "bb"));
assert(assoctree<value>("f", bt) == mklist<value>("f", "ff"));
assert(isNil(assoctree<value>("x", bt)));
return true;
}
double fib_aux(double n, double a, double b) {
if(n == 0.0)
return a;
return fib_aux(n - 1.0, b, a + b);
}
double fib(double n) {
return fib_aux(n, 0.0, 1.0);
}
struct fibMapPerf {
const bool operator()() const {
list<double> s = seq(0.0, 999.0);
list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
}
};
struct nestedFibMapPerf {
const lambda<double(const double)> fib;
nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) {
}
const bool operator()() const {
list<double> s = seq(0.0, 999.0);
list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
}
};
bool testCppPerf() {
{
const lambda<bool()> fml = fibMapPerf();
cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl;
}
{
struct nested {
static double fib(double n) {
struct nested {
static double fib_aux(double n, double a, double b) {
if(n == 0.0)
return a;
return fib_aux(n - 1.0, b, a + b);
}
};
return nested::fib_aux(n, 0.0, 1.0);
}
};
const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib));
cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl;
}
return true;
}
const id<int> idF(const int v) {
return v * 2;
}
const id<int> idG(const int v) {
return v * 3;
}
const id<int> idH(const int v) {
return idF(v) >> idG;
}
bool testIdMonad() {
const id<int> m(2);
assert(m >> idF == idF(2));
assert(m >> unit<int>() == m);
assert(m >> idF >> idG == m >> idH);
return true;
}
const maybe<int> maybeF(const int v) {
return v * 2;
}
const maybe<int> maybeG(const int v) {
return v * 3;
}
const maybe<int> maybeH(const int v) {
return maybeF(v) >> maybeG;
}
bool testMaybeMonad() {
const maybe<int> m(2);
assert(m >> maybeF == maybeF(2));
assert((m >> just<int>()) == m);
assert(m >> maybeF >> maybeG == m >> maybeH);
assert(maybe<int>() >> maybeF >> maybeG == maybe<int>());
return true;
}
const failable<int> failableF(const int v) {
return v * 2;
}
const failable<int> failableG(const int v) {
return v * 3;
}
const failable<int> failableH(const int v) {
return failableF(v) >> failableG;
}
bool testFailableMonad() {
const failable<int> m(2);
assert(m >> failableF == failableF(2));
assert((m >> success<int, string>()) == m);
assert(m >> failableF >> failableG == m >> failableH);
cout << "Failable monad test... " << endl;
failable<int> ooops = mkfailure<int>("test");
assert(reason(ooops) == "test");
assert(ooops >> failableF >> failableG == ooops);
return true;
}
struct tickInc {
const double v;
tickInc(const double v) : v(v) {
}
const scp<int, double> operator()(int s) const {
return scp<int, double>(s + 1, v);
}
};
const state<int, double> tick(const double v) {
return transformer<int, double>(tickInc(v));
}
const state<int, double> stateF(const double v) {
return result<int, double>(v * 2.0) >> tick;
}
const state<int, double> stateG(const double v) {
return result<int, double>(v + 5);
}
const state<int, double> stateH(const double v) {
return stateF(v) >> stateG;
}
bool testStateMonad() {
const lambda<state<int, double>(const double)> r(result<int, double>);
state<int, double> m = result<int, double>(2.0);
assert((m >> stateF)(0) == stateF(2.0)(0));
assert(1 == (int)(m >> stateF)(0));
assert((m >> r)(0) == m(0));
assert((m >> stateF >> stateG)(0) == (m >> stateH)(0));
return true;
}
bool testDynLib() {
const lib dl(string(".libs/libdynlib-test") + dynlibExt);
const failable<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl));
assert(hasContent(sq));
lambda<int(const int)> l(content(sq));
assert(l(2) == 4);
const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl));
assert(hasContent(sql));
lambda<lambda<int(const int)>()> ll(content(sql));
assert(ll()(3) == 9);
return true;
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testLambda();
tuscany::testLambdaGC();
tuscany::testCons();
tuscany::testListGC();
tuscany::testOut();
tuscany::testEquals();
tuscany::testLength();
tuscany::testAppend();
tuscany::testComplex();
tuscany::testMap();
tuscany::testReduce();
tuscany::testFilter();
tuscany::testMember();
tuscany::testReverse();
tuscany::testListRef();
tuscany::testAssoc();
tuscany::testZip();
tuscany::testTokenize();
tuscany::testSeq();
tuscany::testValue();
tuscany::testValueGC();
tuscany::testTree();
tuscany::testTreeAssoc();
tuscany::testCppPerf();
tuscany::testIdMonad();
tuscany::testMaybeMonad();
tuscany::testFailableMonad();
tuscany::testStateMonad();
tuscany::testDynLib();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,559 @@
/*
* 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$ */
#ifndef tuscany_list_hpp
#define tuscany_list_hpp
/**
* Simple list functions.
*/
#include <assert.h>
#include "string.hpp"
#include "fstream.hpp"
#include "function.hpp"
namespace tuscany {
#ifdef WANT_MAINTAINER_MODE
/**
* Debug utilities. Counters used to track instances of lists, and
* macro used to write the contents of a list in a string, easier to
* watch in a debugger than the list itself.
*/
long countLists = 0;
long countILists = 0;
long countCLists = 0;
long countELists = 0;
bool resetListCounters() {
countLists = countILists = countCLists = countELists = 0;
return true;
}
bool checkListCounters() {
return countLists == 0;
}
bool printListCounters() {
cout << "countLists " << countLists << endl;
cout << "countELists " << countELists << endl;
cout << "countILists " << countILists << endl;
cout << "countCLists " << countCLists << endl;
return true;
}
#else
#define resetListCounters()
#define checkListCounters() true
#define printListCounters()
#endif
#ifdef WANT_MAINTAINER_WATCH
#define debug_watchList() do { \
this->watch = watchList(*this); \
} while (0)
#else
#define debug_watchList();
#endif
/**
* A car/cdr lisp-like pair, base structure to construct lists.
*/
template<typename T> class list {
public:
list() {
debug_inc(countLists);
debug_inc(countELists);
debug_watchList();
}
list(const T car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) {
debug_inc(countLists);
debug_inc(countILists);
debug_watchList();
}
list(const list& p) : car(p.car), cdr(p.cdr) {
debug_inc(countLists);
debug_inc(countCLists);
#ifdef WANT_MAINTAINER_WATCH
watch = p.watch;
#endif
}
const list<T>& operator=(const list<T>& p) {
if(this == &p)
return *this;
car = p.car;
cdr = p.cdr;
#ifdef WANT_MAINTAINER_WATCH
watch = p.watch;
#endif
return *this;
}
~list() {
debug_dec(countLists);
}
const bool operator==(const list<T>& p) const {
if(this == &p)
return true;
if(isNil(cdr))
return isNil(p.cdr);
if(isNil(p.cdr))
return false;
if(!(car == p.car))
return false;
if(cdr == p.cdr)
return true;
return cdr() == p.cdr();
}
const bool operator<(const list<T>& p) const {
if(this == &p)
return false;
if (isNil(cdr))
return !isNil(p.cdr);
if (isNil(p.cdr))
return false;
if (car < p.car)
return true;
if (car != p.car)
return false;
return cdr() < p.cdr();
}
const bool operator>(const list<T>& p) const {
if(this == &p)
return false;
if (isNil(cdr))
return false;
if (isNil(p.cdr))
return true;
if (car > p.car)
return true;
if (car != p.car)
return false;
return cdr() > p.cdr();
}
const bool operator!=(const list<T>& p) const {
return !this->operator==(p);
}
operator const list<list<T> >() const {
return (list<list<T> >)T(*this);
}
private:
#ifdef WANT_MAINTAINER_WATCH
template<typename X> friend const string watchList(const list<X>& p);
string watch;
#endif
template<typename X> friend const bool isNil(const list<X>& p);
template<typename X> friend const X car(const list<X>& p);
template<typename X> friend const list<X> cdr(const list<X>& p);
T car;
lambda<list<T>()> cdr;
};
#ifdef WANT_MAINTAINER_WATCH
/**
* Debug utility used to write the contents of a list to a string, easier
* to watch than the list itself in a debugger.
*/
template<typename T> const string watchList(const list<T>& p) {
if(isNil(p))
return "()";
odebugstream os;
os << "(" << car(p) << " ...)";
return str(os);
}
#endif
/**
* Returns true if the given list is nil.
*/
template<typename T> const bool isNil(const list<T>& p) {
return isNil(p.cdr);
}
/**
* Write a list to an output stream.
*/
template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) {
if (isNil(l))
return out;
out << " " << car(l);
return writeHelper(out, cdr(l));
}
template<typename T> ostream& operator<<(ostream& out, const list<T>& l) {
if(isNil(l))
return out << "()";
out << "(" << car(l);
writeHelper<T>(out, cdr(l));
return out << ")";
}
/**
* Construct a (lazy) list from a value and a lambda function that returns the cdr.
*/
template<typename T> const list<T> cons(const T& car, const lambda<list<T>()>& cdr) {
return list<T> (car, cdr);
}
/**
* Construct a list from a value and a cdr list.
*/
template<typename T> const list<T> cons(const T& car, const list<T>& cdr) {
return list<T> (car, result(cdr));
}
/**
* Cons variations for use with the reduce and reduceRight functions.
*/
template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) {
return cons<T>(car, cdr);
}
template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) {
return cons<T>(car, cdr);
}
/**
* Construct a list of one value.
*/
template<typename T> const list<T> mklist(const T& car) {
return list<T> (car, result(list<T> ()));
}
/**
* Construct a list of two values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b) {
return cons(a, mklist(b));
}
/**
* Construct a list of three values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c) {
return cons(a, cons(b, mklist(c)));
}
/**
* Construct a list of four values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d) {
return cons(a, cons(b, cons(c, mklist(d))));
}
/**
* Construct a list of five values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) {
return cons(a, cons(b, cons(c, cons(d, mklist(e)))));
}
/**
* Construct a list of six values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) {
return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f))))));
}
/**
* Returns the car of a list.
*/
template<typename T> const T car(const list<T>& p) {
// Abort if trying to access the car of a nil list
assert(!isNil(p.cdr));
return p.car;
}
/**
* Returns the cdr of a list.
*/
template<typename T> const list<T> cdr(const list<T>& p) {
return p.cdr();
}
/**
* Returns the car of the cdr of a list.
*/
template<typename T> const T cadr(const list<T>& p) {
return car(cdr(p));
}
/**
* Returns the car of the cdr of the cdr of a list.
*/
template<typename T> const T caddr(const list<T>& p) {
return car(cdr(cdr(p)));
}
/**
* Returns the car of the cdr of the cdr of the cdr of a list.
*/
template<typename T> const T cadddr(const list<T>& p) {
return car(cdr(cdr(cdr(p))));
}
/**
* Returns the cdr of a cdr of a list.
*/
template<typename T> const list<T> cddr(const list<T>& p) {
return cdr(cdr(p));
}
/**
* Returns the cdr of a cdr of the cdr of a list.
*/
template<typename T> const list<T> cdddr(const list<T>& p) {
return cdr(cdr(cdr(p)));
}
/**
* Returns the length of a list.
*/
template<typename T> struct lengthRef {
const int operator()(const int c, const list<T>& p) {
if(isNil(p))
return c;
return (*this)(c + 1, cdr(p));
}
};
template<typename T> const int length(const list<T>& p) {
return lengthRef<T> ()(0, p);
}
/**
* Appends a list and a lambda function returning a list.
*/
template<typename T> struct appendCdr {
const list<T> a;
const lambda<list<T>()> fb;
appendCdr(const list<T>& a, const lambda<list<T>()>& fb) :
a(a), fb(fb) {
}
const list<T> operator()() const {
return append(a, fb);
}
};
template<typename T> const list<T> append(const list<T>&a, const lambda<list<T>()>& fb) {
if(isNil(a))
return fb();
return cons<T>(car(a), appendCdr<T> (cdr(a), fb));
}
/**
* Appends two lists.
*/
template<typename T> const list<T> append(const list<T>&a, const list<T>& b) {
return append(a, result(b));
}
/**
* Append a value to a list.
*/
template<typename T> const list<T> operator+(const list<T>& l, const T& v) {
return append(l, mklist(v));
}
template<typename T, typename V> const list<T> operator+(const list<T>& l, const V& v) {
return append(l, mklist<T>(v));
}
/**
* Map a lambda function on a list.
*/
template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, const list<T>& p) {
if(isNil(p))
return list<R> ();
return cons(f(car(p)), map(f, cdr(p)));
}
/**
* Run a reduce lambda function on a list.
*/
template<typename T, typename R> struct reduceAccumulate {
const lambda<R(const R&, const T&)> f;
reduceAccumulate(const lambda<R(const R, const T)>& f) :
f(f) {
}
R operator()(const R& acc, const list<T>& p) const {
if(isNil(p))
return acc;
return (*this)(f(acc, car(p)), cdr(p));
}
};
template<typename T, typename R> const R reduce(const lambda<R(const R, const T)>& f, const R& initial, const list<T>& p) {
return reduceAccumulate<T, R> (f)(initial, p);
}
template<typename T, typename R> struct reduceRightAccumulate {
const lambda<R(const T&, const R&)> f;
reduceRightAccumulate(const lambda<R(const T, const R)>& f) :
f(f) {
}
R operator()(const list<T>& p, const R& acc) const {
if(isNil(p))
return acc;
return (*this)(cdr(p), f(car(p), acc));
}
};
template<typename T, typename R> const R reduceRight(const lambda<R(const T, const R)>& f, const R& initial, const list<T>& p) {
return reduceRightAccumulate<T, R> (f)(p, initial);
}
/**
* Run a filter lambda function on a list.
*/
template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const list<T>& p) {
if(isNil(p))
return list<T> ();
if(f(car(p))) {
const lambda<list<T>(const lambda<bool(const T)>, const list<T>)> ff(filter<T>);
return cons(car(p), curry(ff, f, cdr(p)));
}
return filter(f, cdr(p));
}
/**
* Returns a list pointing to a member of a list.
*/
template<typename T> const list<T> member(const T& t, const list<T>& p) {
if(isNil(p))
return list<T> ();
if(t == car(p))
return p;
return member(t, cdr(p));
}
/**
* Reverse a list.
*/
template<typename T> const list<T> reverseIter(const list<T>& acc, const list<T>& p) {
if(isNil(p))
return acc;
return reverseIter(cons(car(p), acc), cdr(p));
}
template<typename T> const list<T> reverse(const list<T>& p) {
return reverseIter(list<T> (), p);
}
template<typename T> const list<T> seq(const T& start, const T& end);
template<typename T> struct seqGenerate {
const T start;
const T end;
seqGenerate(const T& start, const T&end) :
start(start), end(end) {
}
const list<T> operator()() const {
return seq<T> (start, end);
}
};
/**
* Returns a sequence of values between the given bounds.
*/
template<typename T> const list<T> seq(const T& start, const T& end) {
if(start == end)
return mklist(start);
if(start < end)
return cons<T>(start, seqGenerate<T> (start + 1, end));
return cons<T>(start, seqGenerate<T> (start - 1, end));
}
/**
* Returns the i-th element of a list.
*/
template<typename T> const T listRef(const list<T>& l, const int i) {
if (i == 0)
return car(l);
return listRef(cdr(l), i - 1);
}
/**
* Returns the first pair matching a key from a list of key value pairs.
*/
template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) {
if(isNil(p))
return list<T> ();
if(k == car(car(p)))
return car(p);
return assoc(k, cdr(p));
}
/**
* Returns a list of lists containing elements from two input lists.
*/
template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b) {
if (isNil(a) || isNil(b))
return list<list<T> >();
return cons<list<T> >(mklist<T>(car(a), car(b)), zip(cdr(a), cdr(b)));
}
/**
* Converts a list of key value pairs to a list containing the list of keys and the list of values.
*/
template<typename T> const list<T> unzipKeys(const list<list<T> >& l) {
if (isNil(l))
return list<T>();
return cons(car(car(l)), unzipKeys(cdr(l)));
}
template<typename T> const list<T> unzipValues(const list<list<T> >& l) {
if (isNil(l))
return list<T>();
return cons(cadr(car(l)), unzipValues(cdr(l)));
}
template<typename T> const list<list<T> > unzip(const list<list<T> >& l) {
return mklist<list<T> >(unzipKeys(l), unzipValues(l));
}
}
#endif /* tuscany_list_hpp */

View file

@ -0,0 +1,162 @@
/*
* 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 memory allocation functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "gc.hpp"
#include "function.hpp"
#include "perf.hpp"
namespace tuscany {
int countElements = 0;
int maxElements = 0;
class Element {
public:
Element() : i(0) {
countElements++;
if (countElements > maxElements)
maxElements = countElements;
}
Element(int i) : i(i) {
countElements++;
if (countElements > maxElements)
maxElements = countElements;
}
Element(const Element& o) : i(o.i) {
countElements++;
if (countElements > maxElements)
maxElements = countElements;
}
~Element() {
countElements--;
}
const bool operator==(const Element& o) const {
return o.i == i;
}
private:
friend ostream& operator<<(ostream& out, const Element& v);
int i;
char c[20];
};
ostream& operator<<(ostream& out, const Element& v) {
out << v.i ;
return out;
}
bool poolAlloc(Element** p, const int count) {
if (count == 0)
return true;
p[count - 1] = new (gc_new<Element>()) Element();
return poolAlloc(p, count - 1);
};
bool poolFree(Element** p, const int count) {
if (count == 0)
return true;
// Do nothing to free the element, but cycle through them just
// to get a fair comparison with the other memory alloc tests
return poolFree(p, count - 1);
};
struct poolAllocPerf {
const int n;
Element** p;
poolAllocPerf(const int n) : n(n), p(new Element*[n]) {
}
const bool operator()() const {
gc_scoped_pool gc;
poolAlloc(p, n);
return true;
}
};
bool testPoolAllocPerf() {
const int count = 100000;
const lambda<bool()> pl = poolAllocPerf(count);
maxElements = 0;
cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl;
assert(countElements == 0);
assert(maxElements == count);
return true;
}
bool stdAlloc(Element** p, const int count) {
if (count == 0)
return true;
p[count - 1] = new Element();
return stdAlloc(p, count - 1);
};
bool stdFree(Element** p, const int count) {
if (count == 0)
return true;
delete p[count -1];
return stdFree(p, count - 1);
};
struct stdAllocPerf {
const int n;
Element** p;
stdAllocPerf(const int n) : n(n), p(new Element*[n]) {
}
const bool operator()() const {
stdAlloc(p, n);
stdFree(p, n);
return true;
}
};
bool testStdAllocPerf() {
const int count = 100000;
const lambda<bool()> sl = stdAllocPerf(count);
maxElements = 0;
cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl;
assert(countElements == 0);
assert(maxElements == count);
return true;
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testPoolAllocPerf();
tuscany::testStdAllocPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,486 @@
/*
* 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$ */
#ifndef tuscany_monad_hpp
#define tuscany_monad_hpp
/**
* Simple monad implementations.
*/
#include "function.hpp"
#include "string.hpp"
#include "stream.hpp"
namespace tuscany
{
/**
* Identity monad. Just wraps a value.
* To get the value in the monad, just cast it to the value type.
*/
template<typename V> class id {
public:
id(const V& v) : v(v) {
}
const id<V>& operator=(const id<V>& m) {
if(this == &m)
return *this;
v = m.v;
return *this;
}
const bool operator!=(const id<V>& m) const {
return !this->operator==(m);
}
const bool operator==(const id<V>& m) const {
if (&m == this)
return true;
return v == m.v;
}
private:
const V v;
template<typename X> friend const X content(const id<X>& m);
};
/**
* Write an identity monad to a stream.
*/
template<typename V> ostream& operator<<(ostream& out, const id<V>& m) {
out << content(m);
return out;
}
/**
* Returns the content of an identity monad.
*/
template<typename V> const V content(const id<V>& m) {
return m.v;
}
/**
* Return an identity monad from a value.
*/
template<typename V> const id<V> mkunit(const V& v) {
return id<V>(v);
}
template<typename V> const lambda<id<V>(const V)> unit() {
return mkunit<V>;
}
/**
* Bind a function to an identity monad. Pass the value in the monad to the function.
*/
template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(const V)>& f) {
return f(content(m));
}
template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) {
return f(content(m));
}
/**
* Maybe monad. Used to represent an optional value, which may be there or not.
* To get the value in the monad, just cast it to the value type.
*/
template<typename V> class maybe {
public:
maybe(const V& v) : hasv(true), v(v) {
}
maybe() : hasv(false) {
}
const maybe<V>& operator=(const maybe<V>& m) {
if(this == &m)
return *this;
hasv = m.hasv;
if (hasv)
v = m.v;
return *this;
}
const bool operator!=(const maybe<V>& m) const {
return !this->operator==(m);
}
const bool operator==(const maybe<V>& m) const {
if (this == &m)
return true;
if (!hasv)
return !m.hasv;
return m.hasv && v == m.v;
}
private:
const bool hasv;
V v;
template<typename X> friend const bool hasContent(const maybe<X>& m);
template<typename X> friend const X content(const maybe<X>& m);
};
/**
* Write a maybe monad to a stream.
*/
template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) {
if (!hasContent(m)) {
out << "nothing";
return out;
}
out << content(m);
return out;
}
/**
* Return a maybe monad with a value in it.
*/
template<typename V> const maybe<V> mkjust(const V& v) {
return maybe<V>(v);
}
template<typename V> const lambda<maybe<V>(const V)> just() {
return mkjust<V>;
}
/**
* Returns true if a maybe monad contains a content.
*/
template<typename V> const bool hasContent(const maybe<V>& m) {
return m.hasv;
}
/**
* Returns the content of a maybe monad.
*/
template<typename V> const V content(const maybe<V>& m) {
return m.v;
}
/**
* Bind a function to a maybe monad. Passes the value in the monad to the function
* if present, or does nothing if there's no value.
*/
template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
}
template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) {
if (!hasContent(m))
return m;
return f(content(m));
}
/**
* Failable monad. Used to represent either a success value or a failure.
* To get the value in the monad, just cast it to the value type.
* To get the failure in the monad, cast it to the failure type.
*/
template<typename V, typename F = string> class failable {
public:
failable() : hasv(false) {
}
failable(const V& v) : hasv(true), v(v) {
}
failable(const failable<V, F>& m) : hasv(m.hasv), v(m.v), f(m.f) {
}
const failable<V, F>& operator=(const failable<V, F>& m) {
if (&m == this)
return *this;
hasv = m.hasv;
v = m.v;
f = m.f;
return *this;
}
const bool operator!=(const failable<V, F>& m) const {
return !this->operator==(m);
}
const bool operator==(const failable<V, F>& m) const {
if (this == &m)
return true;
if (!hasv)
return !m.hasv && f == m.f;
return m.hasv && v == m.v;
}
private:
failable(const bool hasv, const F& f) : hasv(hasv), f(f) {
}
template<typename A, typename B> friend const bool hasContent(const failable<A, B>& m);
template<typename A, typename B> friend const A content(const failable<A, B>& m);
template<typename A, typename B> friend const B reason(const failable<A, B>& m);
template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f);
template<typename A> friend const failable<A, string> mkfailure();
bool hasv;
V v;
F f;
};
/**
* Write a failable monad to a stream.
*/
template<typename V, typename F> ostream& operator<<(ostream& out, const failable<V, F>& m) {
if (!hasContent(m)) {
out << reason(m);
return out;
}
out << content(m);
return out;
}
/**
* Returns a failable monad with a success value in it.
*/
template<typename V, typename F> const failable<V, F> mksuccess(const V& v) {
return failable<V, F>(v);
}
template<typename V, typename F> const lambda<failable<V, F>(const V)> success() {
return mksuccess<V, F>;
}
/**
* Returns a failable monad with a failure in it.
*/
template<typename V, typename F> const failable<V, F> mkfailure(const F& f) {
debug(f, "failable::mkfailure");
return failable<V, F>(false, f);
}
template<typename V> const failable<V> mkfailure(const char* f) {
return mkfailure<V, string>(string(f));
}
template<typename V> const failable<V> mkfailure() {
return failable<V, string>(false, string());
}
template<typename V, typename F> const lambda<failable<V, F>(const V)> failure() {
return mkfailure<V, F>;
}
/**
* Returns true if the monad contains a content.
*/
template<typename V, typename F> const bool hasContent(const failable<V, F>& m) {
return m.hasv;
}
/**
* Returns the content of a failable monad.
*/
template<typename V, typename F> const V content(const failable<V, F>& m) {
return m.v;
}
/**
* Returns the reason for failure of a failable monad.
*/
template<typename V, typename F> const F reason(const failable<V, F>& m) {
return m.f;
}
/**
* Bind a function to a failable monad. Passes the success value in the monad to the function
* if present, or does nothing if there's no value and a failure instead.
*/
template<typename R, typename FR, typename V, typename FV>
const failable<R, FR> operator>>(const failable<V, FV>& m, const lambda<failable<R, FR>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
}
template<typename R, typename FR, typename V, typename FV>
const failable<R, FR> operator>>(const failable<V, FV>& m, const failable<R, FR> (* const f)(const V)) {
if (!hasContent(m))
return m;
return f(content(m));
}
/**
* State + content pair data type used by the state monad.
*/
template<typename S, typename V> class scp {
public:
scp(const S& s, const V& v) : s(s), v(v) {
}
operator const S() const {
return s;
}
operator const V() const {
return v;
}
const scp<S, V>& operator=(const scp<S, V>& p) {
if(this == &p)
return *this;
s = p.s;
v = p.v;
return *this;
}
const bool operator!=(const scp<S, V>& p) const {
return !this->operator==(p);
}
const bool operator==(const scp<S, V>& p) const {
if (this == &p)
return true;
return s == p.s && v == p.v;
}
private:
const S s;
const V v;
template<typename A, typename B> friend const A scpstate(const scp<A, B>& m);
template<typename A, typename B> friend const B content(const scp<A, B>& m);
};
/**
* Returns the state of a state-content pair.
*/
template<typename S, typename V> const S scpstate(const scp<S, V>& m) {
return m.s;
}
/**
* Returns the content of a state-content pair.
*/
template<typename S, typename V> const S content(const scp<S, V>& m) {
return m.v;
}
/**
* State monad. Used to represent the combination of a state and a content.
*/
template<typename S, typename V> class state {
public:
state(const lambda<scp<S, V>(const S)>& f) : f(f) {
}
const scp<S, V> operator()(const S& s) const {
return f(s);
}
const state<S, V>& operator=(const state<S, V>& m) {
if(this == &m)
return *this;
f = m.f;
return *this;
}
const bool operator!=(const state<S, V>& m) const {
return !this->operator==(m);
}
const bool operator==(const state<S, V>& m) const {
if (this == &m)
return true;
return f == m.f;
}
private:
const lambda<scp<S, V>(const S)> f;
};
/**
* Write a state monad to a stream.
*/
template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) {
const S s = m;
const V v = m;
out << '(' << s << ' ' << v << ')';
return out;
}
/**
* Return a state monad carrying a result content.
*/
template<typename S, typename V> struct returnState {
const V v;
returnState(const V& v) : v(v) {
}
const scp<S, V> operator()(const S& s) const {
return scp<S, V>(s, v);
}
};
template<typename S, typename V> const state<S, V> result(const V& v) {
return state<S, V>(returnState<S, V>(v));
}
/**
* Return a state monad with a transformer function.
* A transformer function takes a state and returns an scp pair carrying a content and a
* new (transformed) state.
*/
template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(const S)>& f) {
return state<S, V>(f);
}
/**
* Bind a function to a state monad. The function takes a content and returns a state
* monad carrying a return content.
*/
template<typename S, typename A, typename B> struct stateBind {
const state<S, A> st;
const lambda<state<S, B>(const A)>f;
stateBind(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) : st(st), f(f) {
}
const scp<S, B> operator()(const S& is) const {
const scp<S, A> iscp = st(is);
const state<S, B> m = f((A)iscp);
return m((S)iscp);
}
};
template<typename S, typename A, typename B>
const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) {
return state<S, B>(stateBind<S, A , B>(st, f));
}
template<typename S, typename A, typename B>
const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) {
return state<S, B>(stateBind<S, A , B>(st, f));
}
}
#endif /* tuscany_monad_hpp */

Some files were not shown because too many files have changed in this diff Show more