From 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 Mon Sep 17 00:00:00 2001 From: Kim van der Riet Date: Thu, 28 Feb 2013 16:14:30 +0000 Subject: Update from trunk r1375509 through r1450773 git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/bindings/CMakeLists.txt | 67 +++ cpp/bindings/qmf/CMakeLists.txt | 37 -- cpp/bindings/qmf/Makefile.am | 1 - cpp/bindings/qmf/python/CMakeLists.txt | 29 +- cpp/bindings/qmf/python/Makefile.am | 2 +- cpp/bindings/qmf/python/python.i | 2 +- cpp/bindings/qmf/qmfengine.i | 59 --- cpp/bindings/qmf/ruby/CMakeLists.txt | 6 +- cpp/bindings/qmf/ruby/Makefile.am | 2 +- cpp/bindings/qmf/ruby/qmf.rb | 14 +- cpp/bindings/qmf/ruby/ruby.i | 2 +- cpp/bindings/qmf2/CMakeLists.txt | 37 -- cpp/bindings/qmf2/Makefile.am | 1 - cpp/bindings/qmf2/examples/cpp/Makefile.am | 11 +- cpp/bindings/qmf2/python/CMakeLists.txt | 31 +- cpp/bindings/qmf2/python/Makefile.am | 4 +- cpp/bindings/qmf2/python/python.i | 4 +- cpp/bindings/qmf2/qmf2.i | 66 --- cpp/bindings/qmf2/ruby/CMakeLists.txt | 6 +- cpp/bindings/qmf2/ruby/Makefile.am | 4 +- cpp/bindings/qmf2/ruby/ruby.i | 6 +- cpp/bindings/qpid/CMakeLists.txt | 41 -- cpp/bindings/qpid/Makefile.am | 13 +- cpp/bindings/qpid/dotnet/configure-windows.ps1 | 41 +- .../csharp.map.callback.receiver.cs | 28 +- .../org.apache.qpid.messaging.sessionreceiver.sln | 2 +- cpp/bindings/qpid/dotnet/src/Receiver.cpp | 31 +- .../dotnet/src/sessionreceiver/sessionreceiver.cs | 34 +- cpp/bindings/qpid/examples/perl/README | 26 - cpp/bindings/qpid/examples/perl/client.pl | 72 +-- cpp/bindings/qpid/examples/perl/drain.pl | 136 +++-- cpp/bindings/qpid/examples/perl/hello_world.pl | 30 +- cpp/bindings/qpid/examples/perl/hello_xml.pl | 35 +- cpp/bindings/qpid/examples/perl/map_receiver.pl | 28 +- cpp/bindings/qpid/examples/perl/map_sender.pl | 46 +- cpp/bindings/qpid/examples/perl/server.pl | 53 +- cpp/bindings/qpid/examples/perl/spout.pl | 132 +++-- cpp/bindings/qpid/perl/CMakeLists.txt | 13 +- cpp/bindings/qpid/perl/ChangeLog | 6 + cpp/bindings/qpid/perl/LICENSE | 206 ++++++++ cpp/bindings/qpid/perl/Makefile.PL | 13 + cpp/bindings/qpid/perl/README | 15 + .../qpid/perl/lib/qpid/messaging/Address.pm | 338 ++++++++++++ .../qpid/perl/lib/qpid/messaging/Connection.pm | 291 ++++++++++ .../qpid/perl/lib/qpid/messaging/Duration.pm | 204 +++++++ .../qpid/perl/lib/qpid/messaging/Message.pm | 584 +++++++++++++++++++++ .../qpid/perl/lib/qpid/messaging/Receiver.pm | 317 +++++++++++ .../qpid/perl/lib/qpid/messaging/Sender.pm | 258 +++++++++ .../qpid/perl/lib/qpid/messaging/Session.pm | 473 +++++++++++++++++ cpp/bindings/qpid/perl/lib/qpid/messaging/codec.pm | 53 ++ cpp/bindings/qpid/perl/lib/qpid_messaging.pm | 95 ++++ cpp/bindings/qpid/perl/perl.i | 4 +- cpp/bindings/qpid/perl/qpid.pm | 22 + cpp/bindings/qpid/perl/t/Address.t | 102 ++++ cpp/bindings/qpid/perl/t/Duration.t | 124 +++++ cpp/bindings/qpid/perl/t/Message.t | 286 ++++++++++ cpp/bindings/qpid/perl/t/utils.pm | 38 ++ cpp/bindings/qpid/python/CMakeLists.txt | 13 +- cpp/bindings/qpid/python/Makefile.am | 4 +- cpp/bindings/qpid/python/python.i | 4 +- cpp/bindings/qpid/qpid.i | 70 --- cpp/bindings/qpid/ruby/CMakeLists.txt | 6 +- cpp/bindings/qpid/ruby/ChangeLog | 4 + cpp/bindings/qpid/ruby/LICENSE | 4 - cpp/bindings/qpid/ruby/Makefile.am | 4 +- cpp/bindings/qpid/ruby/README.rdoc | 38 +- cpp/bindings/qpid/ruby/Rakefile | 137 ----- cpp/bindings/qpid/ruby/TODO | 15 +- cpp/bindings/qpid/ruby/examples/client.rb | 6 +- cpp/bindings/qpid/ruby/examples/drain.rb | 2 +- cpp/bindings/qpid/ruby/examples/hello_world.rb | 2 +- cpp/bindings/qpid/ruby/examples/map_receiver.rb | 2 +- cpp/bindings/qpid/ruby/examples/map_sender.rb | 2 +- cpp/bindings/qpid/ruby/examples/server.rb | 2 +- cpp/bindings/qpid/ruby/examples/spout.rb | 2 +- cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb | 3 +- .../qpid/ruby/features/creating_a_receiver.feature | 2 +- .../qpid/ruby/features/creating_a_sender.feature | 2 +- .../features/step_definitions/address_steps.rb | 13 +- cpp/bindings/qpid/ruby/features/support/env.rb | 2 +- cpp/bindings/qpid/ruby/lib/qpid.rb | 29 - cpp/bindings/qpid/ruby/lib/qpid/address.rb | 187 ------- cpp/bindings/qpid/ruby/lib/qpid/connection.rb | 162 ------ cpp/bindings/qpid/ruby/lib/qpid/duration.rb | 95 ---- cpp/bindings/qpid/ruby/lib/qpid/encoding.rb | 60 --- cpp/bindings/qpid/ruby/lib/qpid/errors.rb | 33 -- cpp/bindings/qpid/ruby/lib/qpid/message.rb | 368 ------------- cpp/bindings/qpid/ruby/lib/qpid/receiver.rb | 186 ------- cpp/bindings/qpid/ruby/lib/qpid/sender.rb | 152 ------ cpp/bindings/qpid/ruby/lib/qpid/session.rb | 271 ---------- cpp/bindings/qpid/ruby/lib/qpid/version.rb | 31 -- cpp/bindings/qpid/ruby/lib/qpid_messaging.rb | 82 +++ .../qpid/ruby/lib/qpid_messaging/address.rb | 200 +++++++ .../qpid/ruby/lib/qpid_messaging/connection.rb | 189 +++++++ .../qpid/ruby/lib/qpid_messaging/duration.rb | 128 +++++ .../qpid/ruby/lib/qpid_messaging/encoding.rb | 75 +++ .../qpid/ruby/lib/qpid_messaging/message.rb | 353 +++++++++++++ .../qpid/ruby/lib/qpid_messaging/receiver.rb | 177 +++++++ .../qpid/ruby/lib/qpid_messaging/sender.rb | 135 +++++ .../qpid/ruby/lib/qpid_messaging/session.rb | 264 ++++++++++ cpp/bindings/qpid/ruby/qpid_messaging.gemspec | 28 + cpp/bindings/qpid/ruby/ruby.i | 6 +- cpp/bindings/qpid/ruby/spec/qpid/address_spec.rb | 87 --- .../qpid/ruby/spec/qpid/connection_spec.rb | 191 ------- cpp/bindings/qpid/ruby/spec/qpid/duration_spec.rb | 56 -- cpp/bindings/qpid/ruby/spec/qpid/encoding_spec.rb | 63 --- cpp/bindings/qpid/ruby/spec/qpid/message_spec.rb | 292 ----------- cpp/bindings/qpid/ruby/spec/qpid/receiver_spec.rb | 170 ------ cpp/bindings/qpid/ruby/spec/qpid/sender_spec.rb | 135 ----- cpp/bindings/qpid/ruby/spec/qpid/session_spec.rb | 353 ------------- .../qpid/ruby/spec/qpid_messaging/address_spec.rb | 87 +++ .../ruby/spec/qpid_messaging/connection_spec.rb | 191 +++++++ .../qpid/ruby/spec/qpid_messaging/duration_spec.rb | 83 +++ .../qpid/ruby/spec/qpid_messaging/encoding_spec.rb | 63 +++ .../qpid/ruby/spec/qpid_messaging/message_spec.rb | 305 +++++++++++ .../qpid/ruby/spec/qpid_messaging/receiver_spec.rb | 170 ++++++ .../qpid/ruby/spec/qpid_messaging/sender_spec.rb | 135 +++++ .../qpid/ruby/spec/qpid_messaging/session_spec.rb | 353 +++++++++++++ cpp/bindings/qpid/ruby/spec/spec_helper.rb | 3 +- cpp/bindings/swig_perl_typemaps.i | 330 ------------ cpp/bindings/swig_python_typemaps.i | 446 ---------------- cpp/bindings/swig_ruby_typemaps.i | 368 ------------- 122 files changed, 7091 insertions(+), 4921 deletions(-) create mode 100644 cpp/bindings/CMakeLists.txt delete mode 100644 cpp/bindings/qmf/CMakeLists.txt delete mode 100644 cpp/bindings/qmf/qmfengine.i delete mode 100644 cpp/bindings/qmf2/CMakeLists.txt delete mode 100644 cpp/bindings/qmf2/qmf2.i delete mode 100644 cpp/bindings/qpid/CMakeLists.txt delete mode 100644 cpp/bindings/qpid/examples/perl/README mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/client.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/drain.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/hello_world.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/hello_xml.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/map_receiver.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/map_sender.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/server.pl mode change 100644 => 100755 cpp/bindings/qpid/examples/perl/spout.pl create mode 100644 cpp/bindings/qpid/perl/ChangeLog create mode 100644 cpp/bindings/qpid/perl/LICENSE create mode 100644 cpp/bindings/qpid/perl/Makefile.PL create mode 100644 cpp/bindings/qpid/perl/README create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Address.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Connection.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Duration.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Receiver.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Sender.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/Session.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid/messaging/codec.pm create mode 100644 cpp/bindings/qpid/perl/lib/qpid_messaging.pm create mode 100644 cpp/bindings/qpid/perl/qpid.pm create mode 100644 cpp/bindings/qpid/perl/t/Address.t create mode 100644 cpp/bindings/qpid/perl/t/Duration.t create mode 100644 cpp/bindings/qpid/perl/t/Message.t create mode 100644 cpp/bindings/qpid/perl/t/utils.pm delete mode 100644 cpp/bindings/qpid/qpid.i create mode 100644 cpp/bindings/qpid/ruby/ChangeLog delete mode 100644 cpp/bindings/qpid/ruby/Rakefile delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/address.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/connection.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/duration.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/encoding.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/errors.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/message.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/receiver.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/sender.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/session.rb delete mode 100644 cpp/bindings/qpid/ruby/lib/qpid/version.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/address.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/connection.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/duration.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/encoding.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/message.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/receiver.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/sender.rb create mode 100644 cpp/bindings/qpid/ruby/lib/qpid_messaging/session.rb create mode 100644 cpp/bindings/qpid/ruby/qpid_messaging.gemspec delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/address_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/connection_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/duration_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/encoding_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/message_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/receiver_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/sender_spec.rb delete mode 100644 cpp/bindings/qpid/ruby/spec/qpid/session_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/address_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/connection_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/duration_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/encoding_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/message_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/receiver_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/sender_spec.rb create mode 100644 cpp/bindings/qpid/ruby/spec/qpid_messaging/session_spec.rb delete mode 100644 cpp/bindings/swig_perl_typemaps.i delete mode 100644 cpp/bindings/swig_python_typemaps.i delete mode 100644 cpp/bindings/swig_ruby_typemaps.i (limited to 'cpp/bindings') diff --git a/cpp/bindings/CMakeLists.txt b/cpp/bindings/CMakeLists.txt new file mode 100644 index 0000000000..3d44ef01cd --- /dev/null +++ b/cpp/bindings/CMakeLists.txt @@ -0,0 +1,67 @@ +# +# 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. +# + + +include(FindSWIG) +include(UseSWIG) +include(FindRuby) +include(FindPythonLibs) +include(FindPerlLibs) + +set (SWIG_MINIMUM_VERSION "1.3.32") + +if (SWIG_FOUND) + if (${SWIG_VERSION} VERSION_LESS ${SWIG_MINIMUM_VERSION}) + message("Found Swig < ${SWIG_MINIMUM_VERSION} - skipping language bindings") + else() + set(CMAKE_SWIG_FLAGS "-w361,362,401,467,503") + + if (PYTHONLIBS_FOUND) + execute_process(COMMAND ${PYTHON_EXECUTABLE} + -c "from distutils.sysconfig import get_python_lib; print get_python_lib(True, prefix='${CMAKE_INSTALL_PREFIX}')" + OUTPUT_VARIABLE PYTHON_SITEARCH_PACKAGES + OUTPUT_STRIP_TRAILING_WHITESPACE) + + add_subdirectory(qpid/python) + add_subdirectory(qmf2/python) + add_subdirectory(qmf/python) + endif (PYTHONLIBS_FOUND) + + if (RUBY_FOUND) + execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts RbConfig::CONFIG['prefix']" + OUTPUT_VARIABLE RUBY_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE ${RUBY_PREFIX} ${CMAKE_INSTALL_PREFIX} RUBY_PFX_ARCH_DIR ${RUBY_ARCH_DIR}) + + add_subdirectory(qpid/ruby) + add_subdirectory(qmf2/ruby) + add_subdirectory(qmf/ruby) + endif (RUBY_FOUND) + + if (PERLLIBS_FOUND) + execute_process(COMMAND ${PERL_EXECUTABLE} "-V::prefix:" + OUTPUT_VARIABLE QPERL_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "'(.*)'" "\\1" PERL_PREFIX ${QPERL_PREFIX}) + string(REPLACE ${PERL_PREFIX} ${CMAKE_INSTALL_PREFIX} PERL_PFX_ARCHLIB ${PERL_ARCHLIB}) + + add_subdirectory(qpid/perl) + endif (PERLLIBS_FOUND) + endif (${SWIG_VERSION} VERSION_LESS ${SWIG_MINIMUM_VERSION}) +endif (SWIG_FOUND) diff --git a/cpp/bindings/qmf/CMakeLists.txt b/cpp/bindings/qmf/CMakeLists.txt deleted file mode 100644 index 5e40539e80..0000000000 --- a/cpp/bindings/qmf/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# -# 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. -# - - -include(FindSWIG) -include(UseSWIG) -include(FindRuby) -include(FindPythonLibs) -include(FindPerlLibs) - -if (SWIG_FOUND) - set(CMAKE_SWIG_FLAGS "-w362,401") - - if (PYTHONLIBS_FOUND) - add_subdirectory(python) - endif (PYTHONLIBS_FOUND) - - if (RUBY_FOUND) - add_subdirectory(ruby) - endif (RUBY_FOUND) -endif (SWIG_FOUND) diff --git a/cpp/bindings/qmf/Makefile.am b/cpp/bindings/qmf/Makefile.am index dd77ab080c..ee4ff1d3c1 100644 --- a/cpp/bindings/qmf/Makefile.am +++ b/cpp/bindings/qmf/Makefile.am @@ -19,7 +19,6 @@ if HAVE_SWIG -EXTRA_DIST = CMakeLists.txt qmfengine.i SUBDIRS = tests if HAVE_RUBY_DEVEL diff --git a/cpp/bindings/qmf/python/CMakeLists.txt b/cpp/bindings/qmf/python/CMakeLists.txt index 9bc6b2e878..1768df7f85 100644 --- a/cpp/bindings/qmf/python/CMakeLists.txt +++ b/cpp/bindings/qmf/python/CMakeLists.txt @@ -21,7 +21,7 @@ ## Use Swig to generate a literal binding to the C++ API ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES CPLUSPLUS ON) -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include;-I${qpid-cpp_SOURCE_DIR}/bindings") swig_add_module(qmfengine_python python ${CMAKE_CURRENT_SOURCE_DIR}/python.i) swig_link_libraries(qmfengine_python qmf qmfconsole ${PYTHON_LIBRARIES}) @@ -31,28 +31,23 @@ set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_F ##------------------------------------ ## Install the complete Python binding ##------------------------------------ -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmfengine.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmfengine.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/qmf.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmf.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmf.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmfengine.py - ${CMAKE_CURRENT_BINARY_DIR}/qmfengine.pyc - ${CMAKE_CURRENT_BINARY_DIR}/qmfengine.pyo ${CMAKE_CURRENT_SOURCE_DIR}/qmf.py - ${CMAKE_CURRENT_BINARY_DIR}/qmf.pyc - ${CMAKE_CURRENT_BINARY_DIR}/qmf.pyo - DESTINATION ${PYTHON_SITE_PACKAGES} + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/_qmfengine_python.so RENAME _qmfengine.so - DESTINATION ${PYTHON_SITE_PACKAGES} + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) +# Python compile the installed modules +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmfengine.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmfengine.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmf.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmf.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") diff --git a/cpp/bindings/qmf/python/Makefile.am b/cpp/bindings/qmf/python/Makefile.am index bcef8c6b53..07f3c1072b 100644 --- a/cpp/bindings/qmf/python/Makefile.am +++ b/cpp/bindings/qmf/python/Makefile.am @@ -29,7 +29,7 @@ EXTRA_DIST = CMakeLists.txt python.i BUILT_SOURCES = $(generated_file_list) SWIG_FLAGS = -w362,401 -$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmfengine.i +$(generated_file_list): $(srcdir)/python.i $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o qmfengine.cpp $(srcdir)/python.i pylibdir = $(pyexecdir) diff --git a/cpp/bindings/qmf/python/python.i b/cpp/bindings/qmf/python/python.i index 5e25d155f9..118d0d3dbd 100644 --- a/cpp/bindings/qmf/python/python.i +++ b/cpp/bindings/qmf/python/python.i @@ -139,5 +139,5 @@ -%include "../qmfengine.i" +%include "qmf/qmfengine.i" diff --git a/cpp/bindings/qmf/qmfengine.i b/cpp/bindings/qmf/qmfengine.i deleted file mode 100644 index eb350115a3..0000000000 --- a/cpp/bindings/qmf/qmfengine.i +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -%{ - -#include "qmf/engine/Agent.h" -#include "qmf/engine/Console.h" -#include "qmf/engine/ResilientConnection.h" - -%} - -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include - - -%inline { - -using namespace std; -using namespace qmf::engine; - -namespace qmf { -namespace engine { - -} -} -} - - -%{ - -%}; - diff --git a/cpp/bindings/qmf/ruby/CMakeLists.txt b/cpp/bindings/qmf/ruby/CMakeLists.txt index 702606139b..1fb2542e46 100644 --- a/cpp/bindings/qmf/ruby/CMakeLists.txt +++ b/cpp/bindings/qmf/ruby/CMakeLists.txt @@ -22,7 +22,9 @@ ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES CPLUSPLUS ON) -include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include) +include_directories(${RUBY_INCLUDE_DIRS} + ${qpid-cpp_SOURCE_DIR}/include + ${qpid-cpp_SOURCE_DIR}/bindings) swig_add_module(qmfengine_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i) swig_link_libraries(qmfengine_ruby qmf qmfconsole ${RUBY_LIBRARY}) @@ -32,6 +34,6 @@ swig_link_libraries(qmfengine_ruby qmf qmfconsole ${RUBY_LIBRARY}) ##---------------------------------- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libqmfengine_ruby.so RENAME qmfengine.so - DESTINATION ${RUBY_ARCH_DIR} + DESTINATION ${RUBY_PFX_ARCH_DIR} COMPONENT ${QPID_COMPONENT_CLIENT} ) diff --git a/cpp/bindings/qmf/ruby/Makefile.am b/cpp/bindings/qmf/ruby/Makefile.am index 1c7f67edb3..33393aeda0 100644 --- a/cpp/bindings/qmf/ruby/Makefile.am +++ b/cpp/bindings/qmf/ruby/Makefile.am @@ -29,7 +29,7 @@ rubylibdir = $(RUBY_LIB) dist_rubylib_DATA = qmf.rb -qmfengine.cpp: $(srcdir)/ruby.i $(srcdir)/../qmfengine.i +qmfengine.cpp: $(srcdir)/ruby.i $(SWIG) -ruby -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o qmfengine.cpp $(srcdir)/ruby.i rubylibarchdir = $(RUBY_LIB_ARCH) diff --git a/cpp/bindings/qmf/ruby/qmf.rb b/cpp/bindings/qmf/ruby/qmf.rb index 9fbd50cbf6..d05127db4b 100644 --- a/cpp/bindings/qmf/ruby/qmf.rb +++ b/cpp/bindings/qmf/ruby/qmf.rb @@ -319,9 +319,7 @@ module Qmf eventImpl.sessionContext.handler.sess_event_recv(eventImpl.sessionContext, eventImpl.message) end rescue Exception => ex - puts "Event Exception: #{ex}" if bt_count < 2 - puts ex.backtrace bt_count += 1 end end @@ -1251,9 +1249,7 @@ module Qmf when Qmfengine::ConsoleEvent::METHOD_RESPONSE end rescue Exception => ex - puts "Exception caught in callback: #{ex}" if @bt_count < 2 - puts ex.backtrace @bt_count += 1 end end @@ -1381,14 +1377,13 @@ module Qmf end def conn_event_connected() - puts "Console Connection Established..." @session = Session.new(@conn, "qmfc-%s.%d" % [Socket.gethostname, Process::pid], self) @impl.sessionOpened(@session.handle) do_events end def conn_event_disconnected(error) - puts "Console Connection Lost" + end def conn_event_visit @@ -1396,12 +1391,10 @@ module Qmf end def sess_event_session_closed(context, error) - puts "Console Session Lost" @impl.sessionClosed() end def sess_event_recv(context, message) - puts "Unexpected RECV Event" if not @operational @impl.handleRcvMessage(message) do_events end @@ -1510,14 +1503,13 @@ module Qmf end def conn_event_connected() - puts "Agent Connection Established..." @session = Session.new(@conn, "qmfa-%s.%d" % [Socket.gethostname, Process::pid], self) @impl.newSession do_events end def conn_event_disconnected(error) - puts "Agent Connection Lost" + end def conn_event_visit @@ -1525,7 +1517,7 @@ module Qmf end def sess_event_session_closed(context, error) - puts "Agent Session Lost" + end def sess_event_recv(context, message) diff --git a/cpp/bindings/qmf/ruby/ruby.i b/cpp/bindings/qmf/ruby/ruby.i index 0101861100..2854aa0c7e 100644 --- a/cpp/bindings/qmf/ruby/ruby.i +++ b/cpp/bindings/qmf/ruby/ruby.i @@ -102,5 +102,5 @@ } -%include "../qmfengine.i" +%include "qmf/qmfengine.i" diff --git a/cpp/bindings/qmf2/CMakeLists.txt b/cpp/bindings/qmf2/CMakeLists.txt deleted file mode 100644 index 5e40539e80..0000000000 --- a/cpp/bindings/qmf2/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# -# 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. -# - - -include(FindSWIG) -include(UseSWIG) -include(FindRuby) -include(FindPythonLibs) -include(FindPerlLibs) - -if (SWIG_FOUND) - set(CMAKE_SWIG_FLAGS "-w362,401") - - if (PYTHONLIBS_FOUND) - add_subdirectory(python) - endif (PYTHONLIBS_FOUND) - - if (RUBY_FOUND) - add_subdirectory(ruby) - endif (RUBY_FOUND) -endif (SWIG_FOUND) diff --git a/cpp/bindings/qmf2/Makefile.am b/cpp/bindings/qmf2/Makefile.am index 9a03a5cd21..0f50e757a2 100644 --- a/cpp/bindings/qmf2/Makefile.am +++ b/cpp/bindings/qmf2/Makefile.am @@ -19,7 +19,6 @@ if HAVE_SWIG -EXTRA_DIST = CMakeLists.txt qmf2.i SUBDIRS = examples/cpp if HAVE_RUBY_DEVEL diff --git a/cpp/bindings/qmf2/examples/cpp/Makefile.am b/cpp/bindings/qmf2/examples/cpp/Makefile.am index 062fbd0a85..8bf56ead91 100644 --- a/cpp/bindings/qmf2/examples/cpp/Makefile.am +++ b/cpp/bindings/qmf2/examples/cpp/Makefile.am @@ -21,16 +21,19 @@ INCLUDE = -I$(top_srcdir)/include AM_CPPFLAGS = $(INCLUDE) +TYPES_LIB=$(top_builddir)/src/libqpidtypes.la +MESSAGING_LIB=$(top_builddir)/src/libqpidmessaging.la + noinst_PROGRAMS=agent event_driven_list_agents list_agents print_events agent_SOURCES=agent.cpp -agent_LDADD=$(top_builddir)/src/libqmf2.la +agent_LDADD=$(top_builddir)/src/libqmf2.la $(TYPES_LIB) $(MESSAGING_LIB) list_agents_SOURCES=list_agents.cpp -list_agents_LDADD=$(top_builddir)/src/libqmf2.la +list_agents_LDADD=$(top_builddir)/src/libqmf2.la $(MESSAGING_LIB) event_driven_list_agents_SOURCES=event_driven_list_agents.cpp -event_driven_list_agents_LDADD=$(top_builddir)/src/libqmf2.la +event_driven_list_agents_LDADD=$(top_builddir)/src/libqmf2.la $(MESSAGING_LIB) print_events_SOURCES=print_events.cpp -print_events_LDADD=$(top_builddir)/src/libqmf2.la +print_events_LDADD=$(top_builddir)/src/libqmf2.la $(TYPES_LIB) $(MESSAGING_LIB) diff --git a/cpp/bindings/qmf2/python/CMakeLists.txt b/cpp/bindings/qmf2/python/CMakeLists.txt index 2e71ca34e7..1c8447116e 100644 --- a/cpp/bindings/qmf2/python/CMakeLists.txt +++ b/cpp/bindings/qmf2/python/CMakeLists.txt @@ -21,7 +21,7 @@ ## Use Swig to generate a literal binding to the C++ API ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES CPLUSPLUS ON) -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include;-I${qpid-cpp_SOURCE_DIR}/bindings") swig_add_module(cqmf2_python python ${CMAKE_CURRENT_SOURCE_DIR}/python.i) swig_link_libraries(cqmf2_python qmf2 ${PYTHON_LIBRARIES}) @@ -31,28 +31,23 @@ set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_F ##------------------------------------ ## Install the complete Python binding ##------------------------------------ -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cqmf2.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cqmf2.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/qmf2.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmf2.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") -install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmf2.py - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cqmf2.py - ${CMAKE_CURRENT_BINARY_DIR}/cqmf2.pyc - ${CMAKE_CURRENT_BINARY_DIR}/cqmf2.pyo - ${CMAKE_CURRENT_BINARY_DIR}/qmf2.py - ${CMAKE_CURRENT_BINARY_DIR}/qmf2.pyc - ${CMAKE_CURRENT_BINARY_DIR}/qmf2.pyo - DESTINATION ${PYTHON_SITE_PACKAGES} + ${CMAKE_CURRENT_SOURCE_DIR}/qmf2.py + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/_cqmf2_python.so RENAME _cqmf2.so - DESTINATION ${PYTHON_SITE_PACKAGES} + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) +# Python compile the installed modules +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cqmf2.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cqmf2.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile qmf2.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") +install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile qmf2.py + WORKING_DIRECTORY ${PYTHON_SITEARCH_PACKAGES})") diff --git a/cpp/bindings/qmf2/python/Makefile.am b/cpp/bindings/qmf2/python/Makefile.am index 591c1408c0..309e8f8dad 100644 --- a/cpp/bindings/qmf2/python/Makefile.am +++ b/cpp/bindings/qmf2/python/Makefile.am @@ -19,7 +19,7 @@ if HAVE_PYTHON_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src $(QMF_INCLUDES) +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/bindings -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src $(QMF_INCLUDES) generated_file_list = \ cqmf2.cpp \ @@ -29,7 +29,7 @@ EXTRA_DIST = CMakeLists.txt python.i BUILT_SOURCES = $(generated_file_list) SWIG_FLAGS = -w362,401 -$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmf2.i $(srcdir)/../../swig_python_typemaps.i +$(generated_file_list): $(srcdir)/python.i $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/python.i pylibdir = $(pyexecdir) diff --git a/cpp/bindings/qmf2/python/python.i b/cpp/bindings/qmf2/python/python.i index 02dd1632b0..6b5326f8cf 100644 --- a/cpp/bindings/qmf2/python/python.i +++ b/cpp/bindings/qmf2/python/python.i @@ -19,7 +19,7 @@ %module cqmf2 %include "std_string.i" -%include "../../swig_python_typemaps.i" +%include "qpid/swig_python_typemaps.i" /* Define the general-purpose exception handling */ %exception { @@ -37,5 +37,5 @@ } } -%include "../qmf2.i" +%include "qmf/qmf2.i" diff --git a/cpp/bindings/qmf2/qmf2.i b/cpp/bindings/qmf2/qmf2.i deleted file mode 100644 index 0f573fe3e6..0000000000 --- a/cpp/bindings/qmf2/qmf2.i +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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. - */ - -%{ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -%} - -%include -%include -%include - -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include - -%{ - -using namespace qmf; - -%}; - diff --git a/cpp/bindings/qmf2/ruby/CMakeLists.txt b/cpp/bindings/qmf2/ruby/CMakeLists.txt index 1cb969f7dc..70b3e917f9 100644 --- a/cpp/bindings/qmf2/ruby/CMakeLists.txt +++ b/cpp/bindings/qmf2/ruby/CMakeLists.txt @@ -22,7 +22,9 @@ ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES CPLUSPLUS ON) -include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include) +include_directories(${RUBY_INCLUDE_DIRS} + ${qpid-cpp_SOURCE_DIR}/include + ${qpid-cpp_SOURCE_DIR}/bindings) swig_add_module(cqmf2_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i) swig_link_libraries(cqmf2_ruby qmf2 ${RUBY_LIBRARY}) @@ -32,7 +34,7 @@ swig_link_libraries(cqmf2_ruby qmf2 ${RUBY_LIBRARY}) ##---------------------------------- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqmf2_ruby.so RENAME cqmf2.so - DESTINATION ${RUBY_ARCH_DIR} + DESTINATION ${RUBY_PFX_ARCH_DIR} COMPONENT ${QPID_COMPONENT_CLIENT} ) diff --git a/cpp/bindings/qmf2/ruby/Makefile.am b/cpp/bindings/qmf2/ruby/Makefile.am index a03bd6d5e6..9952edb972 100644 --- a/cpp/bindings/qmf2/ruby/Makefile.am +++ b/cpp/bindings/qmf2/ruby/Makefile.am @@ -19,7 +19,7 @@ if HAVE_RUBY_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src $(QMF_INCLUDES) +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/bindings -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src $(QMF_INCLUDES) EXTRA_DIST = CMakeLists.txt ruby.i BUILT_SOURCES = cqmf2.cpp @@ -27,7 +27,7 @@ SWIG_FLAGS = -w362,401 rubylibdir = $(RUBY_LIB) -cqmf2.cpp: $(srcdir)/ruby.i $(srcdir)/../qmf2.i $(srcdir)/../../swig_ruby_typemaps.i +cqmf2.cpp: $(srcdir)/ruby.i $(SWIG) -ruby -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/ruby.i rubylibarchdir = $(RUBY_LIB_ARCH) diff --git a/cpp/bindings/qmf2/ruby/ruby.i b/cpp/bindings/qmf2/ruby/ruby.i index 1070c65a44..0254017555 100644 --- a/cpp/bindings/qmf2/ruby/ruby.i +++ b/cpp/bindings/qmf2/ruby/ruby.i @@ -18,8 +18,10 @@ */ %module cqmf2 +/* Ruby doesn't have a != operator*/ +#pragma SWIG nowarn=378 %include "std_string.i" -%include "../../swig_ruby_typemaps.i" +%include "qpid/swig_ruby_typemaps.i" /* Define the general-purpose exception handling */ %exception { @@ -32,4 +34,4 @@ } } -%include "../qmf2.i" +%include "qmf/qmf2.i" diff --git a/cpp/bindings/qpid/CMakeLists.txt b/cpp/bindings/qpid/CMakeLists.txt deleted file mode 100644 index 7c9f76f991..0000000000 --- a/cpp/bindings/qpid/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -# -# 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. -# - - -include(FindSWIG) -include(UseSWIG) -include(FindRuby) -include(FindPythonLibs) -include(FindPerlLibs) - -if (SWIG_FOUND) - set(CMAKE_SWIG_FLAGS "-w361,362,401,467,503") - - if (PYTHONLIBS_FOUND) - add_subdirectory(python) - endif (PYTHONLIBS_FOUND) - - if (RUBY_FOUND) - add_subdirectory(ruby) - endif (RUBY_FOUND) - - if (PERLLIBS_FOUND) - add_subdirectory(perl) - endif (PERLLIBS_FOUND) -endif (SWIG_FOUND) diff --git a/cpp/bindings/qpid/Makefile.am b/cpp/bindings/qpid/Makefile.am index ae81696f27..aace6f2d95 100644 --- a/cpp/bindings/qpid/Makefile.am +++ b/cpp/bindings/qpid/Makefile.am @@ -21,8 +21,6 @@ SUBDIRS = dotnet if HAVE_SWIG -EXTRA_DIST = CMakeLists.txt qpid.i - if HAVE_RUBY_DEVEL SUBDIRS += ruby endif @@ -33,18 +31,18 @@ endif if HAVE_PERL_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC) +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/bindings -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC) -EXTRA_DIST += perl/perl.i perl/CMakeLists.txt +EXTRA_DIST = perl/perl.i perl/CMakeLists.txt BUILT_SOURCES = perl/cqpid_perl.cpp SWIG_FLAGS = -w362,401 -perl/cqpid_perl.cpp: $(srcdir)/perl/perl.i $(srcdir)/qpid.i $(srcdir)/../swig_perl_typemaps.i +perl/cqpid_perl.cpp: $(srcdir)/perl/perl.i $(SWIG) -perl -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o perl/cqpid_perl.cpp $(srcdir)/perl/perl.i perl/Makefile: perl/cqpid_perl.cpp cd perl; \ - $(PERL) Makefile.PL PREFIX=$(prefix) LIB=$(PERL_ARCHLIB) ; \ + $(PERL) Makefile.PL PREFIX=$(prefix) ; \ cd .. all-local: perl/Makefile @@ -54,7 +52,7 @@ all-local: perl/Makefile install-exec-local: cd perl ; \ - $(MAKE) pure_install DESTDIR=$(prefix) ; \ + $(MAKE) pure_install ; \ cd .. clean-local: @@ -72,7 +70,6 @@ maintainer-clean-local: $(PERL) maintainer-clean ; \ cd .. -DISTCLEANFILES = perl/Makefile.PL CLEANFILES = perl/cqpid_perl.cpp perl/Makefile.old perl/cqpid_perl.pm endif diff --git a/cpp/bindings/qpid/dotnet/configure-windows.ps1 b/cpp/bindings/qpid/dotnet/configure-windows.ps1 index 162ac272b4..60b2b539bd 100644 --- a/cpp/bindings/qpid/dotnet/configure-windows.ps1 +++ b/cpp/bindings/qpid/dotnet/configure-windows.ps1 @@ -24,8 +24,8 @@ # This script configures a qpid\cpp developer build environment under Windows # to enable working with cpp\bindings\qpid\dotnet binding source code. # -# * Supports multiple versions of Visual Studio (VS2008, VS2010) as CMake -# generator. +# * Supports multiple versions of Visual Studio (VS2008, VS2010, VS2012) +# as CMake generator. # # * Supports 32-bit and/or 64-bit development platforms. # @@ -148,10 +148,11 @@ $global:txtWH = 'Write-Host' ############################# # Visual Studio version selection dialog items and choice # -[array]$global:VsVersionCmakeChoiceList = "Visual Studio 2010", "Visual Studio 2008" +[array]$global:VsVersionCmakeChoiceList = "Visual Studio 2012", "Visual Studio 2010", "Visual Studio 2008" $global:vsVersion = '' $global:cmakeGenerator = '' $global:vsSubdir = '' +$global:cmakeCompiler = '' ############################# # Select-Folder @@ -352,18 +353,26 @@ ECHO Environment set for $slnName $studioVersion $vsPlatform $nBits-bit developm function Return-DropDown { if ($DropDown.SelectedItem -ne $null) { $global:vsVersion = $DropDown.SelectedItem.ToString() - if ($global:vsVersion -eq 'Visual Studio 2010') { - $global:cmakeGenerator = "Visual Studio 10" - $global:vsSubdir = "msvc10" + if ($global:vsVersion -eq 'Visual Studio 2012') { + $global:cmakeGenerator = "Visual Studio 11" + $global:vsSubdir = "msvc11" + $global:cmakeCompiler = "-vc110" } else { - if ($global:vsVersion -eq 'Visual Studio 2008') { - $global:cmakeGenerator = "Visual Studio 9 2008" - $global:vsSubdir = "msvc9" - } else { - Write-Host "Visual Studio must be 2008 or 2010" - exit - } - } + if ($global:vsVersion -eq 'Visual Studio 2010') { + $global:cmakeGenerator = "Visual Studio 10" + $global:vsSubdir = "msvc10" + $global:cmakeCompiler = "-vc100" + } else { + if ($global:vsVersion -eq 'Visual Studio 2008') { + $global:cmakeGenerator = "Visual Studio 9 2008" + $global:vsSubdir = "msvc9" + $global:cmakeCompiler = "-vc90" + } else { + Write-Host "Visual Studio must be 2008, 2010, or 2012" + exit + } + } + } $Form.Close() Write-Host "Selected generator: $global:cmakeGenerator" } @@ -496,7 +505,7 @@ if ($make32) { $env:BOOST_ROOT = "$boost32" cd "$build32" Write-Host "Running 32-bit CMake in $build32 ..." - CMake -G "$global:cmakeGenerator" "-DCMAKE_INSTALL_PREFIX=install_x86" $cppDir + CMake -G "$global:cmakeGenerator" "-DGEN_DOXYGEN=No" "-DCMAKE_INSTALL_PREFIX=install_x86" "-DBoost_COMPILER=$global:cmakeCompiler" $cppDir } else { Write-Host "Skipped 32-bit CMake." } @@ -508,7 +517,7 @@ if ($make64) { $env:BOOST_ROOT = "$boost64" cd "$build64" Write-Host "Running 64-bit CMake in $build64" - CMake -G "$global:cmakeGenerator Win64" "-DCMAKE_INSTALL_PREFIX=install_x64" $cppDir + CMake -G "$global:cmakeGenerator Win64" "-DGEN_DOXYGEN=No" "-DCMAKE_INSTALL_PREFIX=install_x64" "-DBoost_COMPILER=$global:cmakeCompiler" $cppDir } else { Write-Host "Skipped 64-bit CMake." } diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/csharp.map.callback.receiver.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/csharp.map.callback.receiver.cs index b1ba949e07..3bc22b2ce8 100644 --- a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/csharp.map.callback.receiver.cs +++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/csharp.map.callback.receiver.cs @@ -152,6 +152,21 @@ namespace Org.Apache.Qpid.Messaging.Examples } + /// + /// SessionReceiver implements the ISessionReceiver interface. + /// It is the exception function that receives all exception messages + /// It may be called any time server is running. + /// It is always called on server's private thread. + /// After this is called then the sessionReceiver and private thread are closed. + /// + /// The exception. + public void SessionException(Exception exception) + { + // A typical application will take more action here. + Console.WriteLine("{0} Exception caught.", exception.ToString()); + } + + /// /// Usage /// @@ -259,8 +274,17 @@ namespace Org.Apache.Qpid.Messaging.Examples // // Close the receiver and the connection. // - receiver.Close(); - connection.Close(); + try + { + receiver.Close(); + connection.Close(); + } + catch (Exception exception) + { + // receiver or connection may throw if they closed in error. + // A typical application will take more action here. + Console.WriteLine("{0} Closing exception caught.", exception.ToString()); + } return 0; } } diff --git a/cpp/bindings/qpid/dotnet/msvc9/org.apache.qpid.messaging.sessionreceiver.sln b/cpp/bindings/qpid/dotnet/msvc9/org.apache.qpid.messaging.sessionreceiver.sln index 9ed7d4df3a..112511e5e5 100644 --- a/cpp/bindings/qpid/dotnet/msvc9/org.apache.qpid.messaging.sessionreceiver.sln +++ b/cpp/bindings/qpid/dotnet/msvc9/org.apache.qpid.messaging.sessionreceiver.sln @@ -21,7 +21,7 @@ Microsoft Visual Studio Solution File, Format Version 10.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Org.Apache.Qpid.Messaging", "..\src\msvc9\org.apache.qpid.messaging.vcproj", "{AA5A3B83-5F98-406D-A01C-5A921467A57D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "org.apache.qpid.messaging.sessionreceiver", "..\src\msvc9\sessionreceiver\org.apache.qpid.messaging.sessionreceiver.csproj", "{B0A51CEC-30A2-4C2E-90BE-AE95107EAA05}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "org.apache.qpid.messaging.sessionreceiver", "..\src\sessionreceiver\msvc9\org.apache.qpid.messaging.sessionreceiver.csproj", "{B0A51CEC-30A2-4C2E-90BE-AE95107EAA05}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/cpp/bindings/qpid/dotnet/src/Receiver.cpp b/cpp/bindings/qpid/dotnet/src/Receiver.cpp index bbd7dd4c52..43bb7dd3cb 100644 --- a/cpp/bindings/qpid/dotnet/src/Receiver.cpp +++ b/cpp/bindings/qpid/dotnet/src/Receiver.cpp @@ -344,9 +344,34 @@ namespace Messaging { void Receiver::Close() { - msclr::lock lk(privateLock); - ThrowIfDisposed(); + System::Exception ^ newException = nullptr; + Message ^ newMessage = nullptr; - nativeObjPtr->close(); + try + { + msclr::lock lk(privateLock); + ThrowIfDisposed(); + + nativeObjPtr->close(); + } + catch (const ::qpid::types::Exception & error) + { + String ^ errmsg = gcnew String(error.what()); + newException = gcnew QpidException(errmsg); + } + finally + { + if (newException != nullptr) + { + if (newMessage != nullptr) + { + delete newMessage; + } + } + } + if (newException != nullptr) + { + throw newException; + } } }}}} diff --git a/cpp/bindings/qpid/dotnet/src/sessionreceiver/sessionreceiver.cs b/cpp/bindings/qpid/dotnet/src/sessionreceiver/sessionreceiver.cs index 680732068f..a15a8d60fe 100644 --- a/cpp/bindings/qpid/dotnet/src/sessionreceiver/sessionreceiver.cs +++ b/cpp/bindings/qpid/dotnet/src/sessionreceiver/sessionreceiver.cs @@ -37,6 +37,7 @@ namespace Org.Apache.Qpid.Messaging.SessionReceiver public interface ISessionReceiver { void SessionReceiver(Receiver receiver, Message message); + void SessionException(Exception exception); } @@ -67,25 +68,32 @@ namespace Org.Apache.Qpid.Messaging.SessionReceiver { Receiver rcvr; Message msg; - - keepRunning = true; - while (keepRunning) + try { - rcvr = session.NextReceiver(DurationConstants.SECOND); - - if (null != rcvr) + keepRunning = true; + while (keepRunning) { - if (keepRunning) + rcvr = session.NextReceiver(DurationConstants.SECOND); + + if (null != rcvr) { - msg = rcvr.Fetch(DurationConstants.SECOND); - this.callback.SessionReceiver(rcvr, msg); + if (keepRunning) + { + msg = rcvr.Fetch(DurationConstants.SECOND); + this.callback.SessionReceiver(rcvr, msg); + } } + //else + // receive timed out + // EventEngine exits the nextReceiver() function periodically + // in order to test the keepRunning flag } - //else - // receive timed out - // EventEngine exits the nextReceiver() function periodically - // in order to test the keepRunning flag } + catch (Exception e) + { + this.callback.SessionException(e); + } + // Private thread is now exiting. } diff --git a/cpp/bindings/qpid/examples/perl/README b/cpp/bindings/qpid/examples/perl/README deleted file mode 100644 index 1e113f1fa0..0000000000 --- a/cpp/bindings/qpid/examples/perl/README +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - - -The examples in this directory are written against the raw Perl -binding ("cqpid"). This binding is identical to the C++ messaging (in -namespace qpid::messaging). - -It is desired that a layer will be written over this interface (called -"qpid") that provides a more Perl-specific API. When this occurs, -these examples will be changed to use the new Perl API. - diff --git a/cpp/bindings/qpid/examples/perl/client.pl b/cpp/bindings/qpid/examples/perl/client.pl old mode 100644 new mode 100755 index 19d9d3f14f..586beb787e --- a/cpp/bindings/qpid/examples/perl/client.pl +++ b/cpp/bindings/qpid/examples/perl/client.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -20,47 +20,59 @@ use strict; use warnings; -use cqpid_perl; +use qpid; -my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; -my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : ""; +my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; +my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : ""; - -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# creates a new connection instance +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { -$connection->open(); -my $session = $connection->createSession(); + # open the connection and create a session for interacting with it + $connection->open(); -my $sender = $session->createSender("service_queue"); + my $session = $connection->create_session(); + my $sender = $session->create_sender("service_queue"); -#create temp queue & receiver... -my $responseQueue = new cqpid_perl::Address("#response-queue; {create:always, delete:always}"); -my $receiver = $session->createReceiver($responseQueue); + # create an address and receiver for incoming messages + # the queue will be created always, and will be deleted + # when the receive disconnects + my $responseQueue = new qpid::messaging::Address( + "#response-queue; {create:always, delete:always}"); + my $receiver = $session->create_receiver($responseQueue); -#Now send some messages... + # Now send some messages... -my @s = ( - "Twas brillig, and the slithy toves", - "Did gire and gymble in the wabe.", - "All mimsy were the borogroves,", - "And the mome raths outgrabe." - ); + my @s = ( + "Twas brillig, and the slithy toves", + "Did gire and gymble in the wabe.", + "All mimsy were the borogroves,", + "And the mome raths outgrabe." + ); -my $request = new cqpid_perl::Message(); -$request->setReplyTo($responseQueue); -for (my $i=0; $i<4; $i++) { - $request->setContent($s[$i]); - $sender->send($request); - my $response = $receiver->fetch(); - print $request->getContent() . " -> " . $response->getContent() . "\n"; -} + # create the message object, and set a reply-to address + # so that the server knows where to send responses + # the message object will be reused to send each line + my $request = new qpid::messaging::Message(); + $request->set_reply_to($responseQueue); + for ( my $i = 0 ; $i < 4 ; $i++ ) { + $request->set_content( $s[$i] ); + $sender->send($request); + + # wait for the response to the last line sent + # the message will be taken directly from the + # broker's queue rather than waiting for it + # to be queued locally + my $response = $receiver->fetch(); + print $request->get_content() . " -> " + . $response->get_content() . "\n"; + } -$connection->close(); + # close the connection + $connection->close(); }; if ($@) { die $@; } - - diff --git a/cpp/bindings/qpid/examples/perl/drain.pl b/cpp/bindings/qpid/examples/perl/drain.pl old mode 100644 new mode 100755 index 60ac0c50ed..f7a710c485 --- a/cpp/bindings/qpid/examples/perl/drain.pl +++ b/cpp/bindings/qpid/examples/perl/drain.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -20,79 +20,135 @@ use strict; use warnings; -use cqpid_perl; +use qpid; use Getopt::Long; +use Pod::Usage; -my $url = "127.0.0.1"; -my $timeout = 60; -my $forever = 0; -my $count = 1; +my $url = "127.0.0.1"; +my $timeout = 0; +my $forever = 0; +my $count = 0; my $connectionOptions = ""; -my $address = "amq.direct"; +my $address = "amq.direct"; +my $help; my $result = GetOptions( - "broker|b=s" => \ $url, - "timeout|t=i" => \ $timeout, - "forever|f" => \ $forever, - "connection-options=s" => \ $connectionOptions, - "count|c=i" => \ $count, -); - -if (! $result) { - print "Usage: perl drain.pl [OPTIONS]\n"; -} + "broker|b=s" => \$url, + "timeout|t=i" => \$timeout, + "forever|f" => \$forever, + "connection-options=s" => \$connectionOptions, + "count|c=i" => \$count, + "help|h" => \$help +) || pod2usage( -verbose => 0 ); + +pod2usage( -verbose => 1 ) if $help; -if ($#ARGV ge 0) { - $address = $ARGV[0] +if ( $#ARGV ge 0 ) { + $address = $ARGV[0]; } sub getTimeout { - return ($forever) ? $cqpid_perl::Duration::FOREVER : new cqpid_perl::Duration($timeout*1000); + + # returns either the named duration FOREVER if the + # forever cmdline argument was used, otherwise creates + # a new Duration of the specified length + return ($forever) + ? qpid::messaging::Duration::FOREVER + : new qpid::messaging::Duration( $timeout * 1000 ); } +sub printProperties { + my $h = shift(); + return qq[{${\(join', ',map"'$_': '$h->{$_}'",keys%$h)}}]; +} -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# create a connection object +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { + # open the connection, then create a session and receiver $connection->open(); - my $session = $connection->createSession(); - my $receiver = $session->createReceiver($address); + my $session = $connection->create_session(); + my $receiver = $session->create_receiver($address); my $timeout = getTimeout(); + my $message = new qpid::messaging::Message(); + my $i = 0; + + for ( ; ; ) { + eval { $message = $receiver->fetch($timeout); }; - my $message = new cqpid_perl::Message(); - my $i = 0; + if ($@) { + last; + } + + # check if the message was on that was redelivered + my $redelivered = + ( $message->get_redelivered ) ? "redelivered=True, " : ""; + print "Message(" + . $redelivered + . "properties=" + . printProperties( $message->get_properties() ) + . ", content='"; - while($receiver->fetch($message, $timeout)) { - print "Message(properties=" . $message->getProperties() . ",content='"; - if ($message->getContentType() eq "amqp/map") { - my $content = cqpid_perl::decodeMap($message); - map{ print "\n$_ => $content->{$_}"; } keys %{$content}; + # if the message content was a map, then we will print + # it out as a series of name => value pairs + if ( $message->get_content_type() eq "amqp/map" ) { + my $content = $message->get_content(); + map { print "\n$_ => $content->{$_}"; } keys %{$content}; } else { - print $message->getContent(); + # it's not a map, so just print the content as a string + print $message->get_content(); } print "')\n"; - - my $replyto = $message->getReplyTo(); - if ($replyto->getName()) { - print "Replying to " . $message->getReplyTo()->str() . "...\n"; - my $sender = $session->createSender($replyto); - my $response = new cqpid_perl::Message("received by the server."); + + # if the message had a reply-to address, then we'll send a + # response back letting the send know the message was processed + my $replyto = $message->get_reply_to(); + if ( $replyto->get_name() ) { + print "Replying to " . $message->get_reply_to()->str() . "...\n"; + + # create a temporary sender for the specified queue + my $sender = $session->create_sender($replyto); + my $response = + new qpid::messaging::Message("received by the server."); $sender->send($response); } + + # acknowledge all messages received on this queue so far $session->acknowledge(); - if ($count and (++$i ==$count)) { + if ( $count and ( ++$i == $count ) ) { last; } } + + # close everything to clean up $receiver->close(); $session->close(); $connection->close(); }; if ($@) { - $connection->close(); - die $@; + $connection->close(); + die $@; } +__END__ + +=head1 NAME + +drain - Drains messages from the specified address + +=head1 SYNOPSIS + + Options: + -h, --help show this message + -b VALUE, --broker VALUE url of broker to connect to + -t VALUE, --timeout VALUE timeout in seconds to wait before exiting + -f, --forever ignore timeout and wait forever + --connection-options VALUE connection options string in the form {name1:value1, name2:value2} + -c VALUE, --count VALUE number of messages to read before exiting + +=cut + diff --git a/cpp/bindings/qpid/examples/perl/hello_world.pl b/cpp/bindings/qpid/examples/perl/hello_world.pl old mode 100644 new mode 100755 index a96b98a002..6ec7d52f1f --- a/cpp/bindings/qpid/examples/perl/hello_world.pl +++ b/cpp/bindings/qpid/examples/perl/hello_world.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -21,35 +21,35 @@ use strict; use warnings; use Data::Dumper; -use cqpid_perl; +use qpid; my $broker = ( @ARGV > 0 ) ? $ARGV[0] : "localhost:5672"; my $address = ( @ARGV > 1 ) ? $ARGV[0] : "amq.topic"; my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[1] : ""; -my $connection = new cqpid_perl::Connection($broker, $connectionOptions); +# create a connection +my $connection = new qpid::messaging::Connection( $broker, $connectionOptions ); eval { + # open the connection and create a session, and both a sender a receive $connection->open(); - my $session = $connection->createSession(); - my $receiver = $session->createReceiver($address); - my $sender = $session->createSender($address); + my $session = $connection->create_session(); - $sender->send(new cqpid_perl::Message("Hello world!")); + my $receiver = $session->create_receiver($address); + my $sender = $session->create_sender($address); - #my $duration = new cqpid_perl::Duration(1000); - #print ">>>" . $duration->getMilliseconds() . "\n"; + # send a simple message + $sender->send( new qpid::messaging::Message("Hello world!") ); - my $message = $receiver->fetch($cqpid_perl::Duration::SECOND); + # receive the message, fetching it directly from the broker + my $message = $receiver->fetch(qpid::messaging::Duration::SECOND); - #$message->setDurable(1); - #print "Durable: " . $message->getDurable() . "\n"; - #print Dumper($message->getProperties()); - - print $message->getContent() . "\n"; + # output the message content, then acknowledge it + print $message->get_content() . "\n"; $session->acknowledge(); + # close the connection $connection->close(); }; diff --git a/cpp/bindings/qpid/examples/perl/hello_xml.pl b/cpp/bindings/qpid/examples/perl/hello_xml.pl old mode 100644 new mode 100755 index cebf2ceee6..8d77c4b2b8 --- a/cpp/bindings/qpid/examples/perl/hello_xml.pl +++ b/cpp/bindings/qpid/examples/perl/hello_xml.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -20,7 +20,7 @@ use strict; use warnings; -use cqpid_perl; +use qpid; my $broker = ( @ARGV > 0 ) ? $ARGV[0] : "localhost:5672"; my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : ""; @@ -36,23 +36,25 @@ END my $address = <open(); - my $session = $connection->createSession(); + my $session = $connection->create_session(); + my $receiver = $session->create_receiver($address); - my $receiver = $session->createReceiver($address); - - my $message = new cqpid_perl::Message(); + # create a message and set its contentn + my $message = new qpid::messaging::Message(); my $content = < @@ -62,14 +64,19 @@ eval { 35 END - - $message->setContent($content); - my $sender = $session->createSender('xml-exchange/weather'); + + $message->set_content($content); + + # create a sender for the xml-exchange/weater topic + # then send the message + my $sender = $session->create_sender('xml-exchange/weather'); $sender->send($message); - + + # wait for the response and then output it to the screen my $response = $receiver->fetch(); - print $response->getContent() . "\n"; + print $response->get_content() . "\n"; + # close the connection $connection->close(); }; diff --git a/cpp/bindings/qpid/examples/perl/map_receiver.pl b/cpp/bindings/qpid/examples/perl/map_receiver.pl old mode 100644 new mode 100755 index 2e2611e38f..a538adf380 --- a/cpp/bindings/qpid/examples/perl/map_receiver.pl +++ b/cpp/bindings/qpid/examples/perl/map_receiver.pl @@ -1,4 +1,4 @@ -#! /usr/bin/perl5 +#! /usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -21,25 +21,33 @@ use strict; use warnings; use Data::Dumper; -use cqpid_perl; +use qpid; -my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; -my $address = ( @ARGV > 1 ) ? $ARGV[0] : "message_queue; {create: always}"; +my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; +my $address = ( @ARGV > 1 ) ? $ARGV[0] : "message_queue; {create: always}"; my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[1] : ""; -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# create a connection object +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { + # open the connection, then create a session from it $connection->open(); - my $session = $connection->createSession(); - my $receiver = $session->createReceiver($address); + my $session = $connection->create_session(); - my $content = cqpid_perl::decodeMap($receiver->fetch()); - #my $content = cqpid_perl::decodeList($receiver->fetch()); - + # create a receiver for the session, subscribed the the specified queue + my $receiver = $session->create_receiver($address); + # wait for a message to appear in the queue + my $message = $receiver->fetch(); + + # display the content of the message + my $content = $message->get_content(); print Dumper($content); + # acknowledge the message, removing it from the queue $session->acknowledge(); + + # close everything, cleaning up $receiver->close(); $connection->close(); }; diff --git a/cpp/bindings/qpid/examples/perl/map_sender.pl b/cpp/bindings/qpid/examples/perl/map_sender.pl old mode 100644 new mode 100755 index 4107cd48b9..27063ef780 --- a/cpp/bindings/qpid/examples/perl/map_sender.pl +++ b/cpp/bindings/qpid/examples/perl/map_sender.pl @@ -1,4 +1,4 @@ -#! /usr/bin/perl5 +#! /usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -21,29 +21,39 @@ use strict; use warnings; use Data::Dumper; -use cqpid_perl; +use qpid; -my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; -my $address = ( @ARGV > 1 ) ? $ARGV[1] : "message_queue; {create: always}"; +my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; +my $address = ( @ARGV > 1 ) ? $ARGV[1] : "message_queue; {create: always}"; my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[2] : ""; -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# create a new connection object +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { - $connection->open(); - - my $session = $connection->createSession(); - my $sender = $session->createSender($address); - - my $message = new cqpid_perl::Message(); - my $content = { id => 987654321, - name => "Widget", - percent => sprintf("%.2f", 0.99), - colours => [ qw (red green white) ], - }; - cqpid_perl::encode($content, $message); - $sender->send($message, 1); + # open the connection and create a session + $connection->open(); + my $session = $connection->create_session(); + + # create a sender and connect it to the supplied address string + my $sender = $session->create_sender($address); + + # create a message and set the content to be a map of values + my $message = new qpid::messaging::Message(); + my $content = { + id => 987654321, + name => "Widget", + percent => sprintf( "%.2f", 0.99 ), + colours => [qw (red green white)], + }; + $message->set_content($content); + + # send the message + $sender->send( $message, 1 ); + + # close the connection and session + $session->close(); $connection->close(); }; diff --git a/cpp/bindings/qpid/examples/perl/server.pl b/cpp/bindings/qpid/examples/perl/server.pl old mode 100644 new mode 100755 index b14da565b9..be43655aeb --- a/cpp/bindings/qpid/examples/perl/server.pl +++ b/cpp/bindings/qpid/examples/perl/server.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -20,43 +20,64 @@ use strict; use warnings; -use cqpid_perl; +use qpid; -my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; -my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : ""; +my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672"; +my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : ""; - -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# create a connection object +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { + + # connect to the broker and create a session $connection->open(); - my $session = $connection->createSession(); + my $session = $connection->create_session(); - my $receiver = $session->createReceiver("service_queue; {create: always}"); + # create a receiver for accepting incoming messages + my $receiver = $session->create_receiver("service_queue; {create: always}"); + # go into an infinite loop to receive messages and process them while (1) { + + # wait for the next message to be processed my $request = $receiver->fetch(); - my $address = $request->getReplyTo(); + + + # get the address for sending replies + # if no address was supplised then we can't really respond, so + # only process when one is present + my $address = $request->get_reply_to(); if ($address) { - my $sender = $session->createSender($address); - my $s = $request->getContent(); + + # a temporary sender for sending to the response queue + my $sender = $session->create_sender($address); + my $s = $request->get_content(); $s = uc($s); - my $response = new cqpid_perl::Message($s); + + # create the response message and send it + my $response = new qpid::messaging::Message($s); $sender->send($response); - print "Processed request: " . $request->getContent() . " -> " . $response->getContent() . "\n"; + print "Processed request: " + . $request->get_content() . " -> " + . $response->get_content() . "\n"; + + # acknowledge the message since it was processed $session->acknowledge(); } else { - print "Error: no reply address specified for request: " . $request->getContent() . "\n"; + print "Error: no reply address specified for request: " + . $request->get_content() . "\n"; $session->reject($request); } } -$connection->close(); + # close connections to clean up + $session->close(); + $connection->close(); }; if ($@) { die $@; } - diff --git a/cpp/bindings/qpid/examples/perl/spout.pl b/cpp/bindings/qpid/examples/perl/spout.pl old mode 100644 new mode 100755 index 7365e732bf..d8ac860143 --- a/cpp/bindings/qpid/examples/perl/spout.pl +++ b/cpp/bindings/qpid/examples/perl/spout.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -20,117 +20,145 @@ use strict; use warnings; -use cqpid_perl; +use qpid; use Getopt::Long; +use Pod::Usage; use Time::Local; -my $url = "127.0.0.1"; +my $url = "127.0.0.1"; my $timeout = 0; my $count = 1; my $id = ""; my $replyto = ""; my @properties; my @entries; -my $content = ""; +my $content = ""; my $connectionOptions = ""; -my $address = "amq.direct"; +my $address = "amq.direct"; +my $help; my $result = GetOptions( - "broker|b=s" => \ $url, - "timeout|t=i" => \ $timeout, - "count|c=i" => \ $count, - "id|i=s" => \ $id, - "replyto=s" => \ $replyto, - "property|p=s@" => \ @properties, - "map|m=s@" => \ @entries, - "content=s" => \ $content, - "connection-options=s" => \ $connectionOptions, -); - - -if (! $result) { - print "Usage: perl drain.pl [OPTIONS]\n"; + "broker|b=s" => \$url, + "timeout|t=i" => \$timeout, + "count|c=i" => \$count, + "id|i=s" => \$id, + "replyto=s" => \$replyto, + "property|p=s@" => \@properties, + "map|m=s@" => \@entries, + "content=s" => \$content, + "connection-options=s" => \$connectionOptions, + "help|h" => \$help +) || pod2usage( -verbose => 0 ); + +pod2usage( -verbose => 1 ) if $help; + +if ( $#ARGV ge 0 ) { + $address = $ARGV[0]; } - -if ($#ARGV ge 0) { - $address = $ARGV[0] -} - - sub setEntries { my ($content) = @_; foreach (@entries) { - my ($name, $value) = split("=", $_); + my ( $name, $value ) = split( "=", $_ ); $content->{$name} = $value; } } - sub setProperties { my ($message) = @_; foreach (@properties) { - my ($name, $value) = split("=", $_); - $message->getProperties()->{$name} = $value; + my ( $name, $value ) = split( "=", $_ ); + $message->setProperty( $name, $value ); } } -my $connection = new cqpid_perl::Connection($url, $connectionOptions); +# create a connection object +my $connection = new qpid::messaging::Connection( $url, $connectionOptions ); eval { + # open the connection, create a session and then a sender $connection->open(); - my $session = $connection->createSession(); - my $sender = $session->createSender($address); + my $session = $connection->create_session(); + my $sender = $session->create_sender($address); - my $message = new cqpid_perl::Message(); + # create a message to be sent + my $message = new qpid::messaging::Message(); setProperties($message) if (@properties); if (@entries) { my $content = {}; setEntries($content); - cqpid_perl::encode($content, $message); + $message->set_content($content); } elsif ($content) { - $message->setContent($content); - $message->setContentType("text/plain"); + $message->set_content($content); + $message->set_content_type("text/plain"); } + # if a reply-to address was supplied, then create a receiver from the + # session and wait for a response to be sent my $receiver; if ($replyto) { - my $responseQueue = new cqpid_perl::Address($replyto); - $receiver = $session->createReceiver($responseQueue); - $message->setReplyTo($responseQueue); + my $responseQueue = new qpid::messaging::Address($replyto); + $receiver = $session->create_receiver($responseQueue); + $message->set_reply_to($responseQueue); } my $start = localtime; - my @s = split(/[:\s]/, $start); - my $s = "$s[3]$s[4]$s[5]"; - my $n = $s; - - for (my $i = 0; - ($i < $count || $count == 0) and - ($timeout == 0 || abs($n - $s) < $timeout); - $i++) { + my @s = split( /[:\s]/, $start ); + my $s = "$s[3]$s[4]$s[5]"; + my $n = $s; + + for ( + my $i = 0 ; + ( $i < $count || $count == 0 ) + and ( $timeout == 0 || abs( $n - $s ) < $timeout ) ; + $i++ + ) + { $sender->send($message); if ($receiver) { + print "Waiting for a response.\n"; my $response = $receiver->fetch(); - print "$i -> " . $response->getContent() . "\n"; + print "$i -> " . $response->get_content() . "\n"; } my $now = localtime; - my @n = split(/[:\s]/, $now); - my $n = "$n[3]$n[4]$n[5]"; + my @n = split( /[:\s]/, $now ); + my $n = "$n[3]$n[4]$n[5]"; } $session->sync(); $connection->close(); }; if ($@) { - $connection->close(); - die $@; + $connection->close(); + die $@; } +__END__ + +=head1 NAME + +spout - Send messages to the specified address + +=head1 SYNOPSIS + + Usage: spout [OPTIONS] ADDRESS + + Options: + -h, --help show this message + -b VALUE, --broker VALUE url of broker to connect to + -t VALUE, --timeout VALUE exit after the specified time + -c VALUE, --count VALUE stop after count messageshave been sent, zero disables + -i VALUE, --id VALUE use the supplied id instead of generating one + --replyto VALUE specify reply-to value + -P VALUE, --property VALUE specify message property + -M VALUE, --map VALUE specify entry for map content + --content VALUE specify textual content + --connection-options VALUE connection options string in the form {name1:value1, name2:value2} +=cut diff --git a/cpp/bindings/qpid/perl/CMakeLists.txt b/cpp/bindings/qpid/perl/CMakeLists.txt index 0d66c144db..a1380fa4d0 100644 --- a/cpp/bindings/qpid/perl/CMakeLists.txt +++ b/cpp/bindings/qpid/perl/CMakeLists.txt @@ -21,18 +21,25 @@ ## Use Swig to generate a literal binding to the C++ API ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/perl.i PROPERTIES CPLUSPLUS ON) -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/perl.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/perl.i + PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include;-I${qpid-cpp_SOURCE_DIR}/include;-I${qpid-cpp_SOURCE_DIR}/bindings") swig_add_module(cqpid_perl perl ${CMAKE_CURRENT_SOURCE_DIR}/perl.i) swig_link_libraries(cqpid_perl qpidmessaging qpidtypes qmf2 ${PERL_LIBRARY}) -set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${PERL_INCLUDE_PATH} -I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing") +include_directories(${PERL_INCLUDE_PATH} + ${qpid-cpp_SOURCE_DIR}/include + ${qpid-cpp_SOURCE_DIR}/bindings) ##---------------------------------- ## Install the complete Perl binding ##---------------------------------- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid_perl.so ${CMAKE_CURRENT_BINARY_DIR}/cqpid_perl.pm - DESTINATION ${PERL_ARCHLIB} + ${CMAKE_CURRENT_SOURCE_DIR}/qpid.pm + ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE + ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.PL + DESTINATION ${PERL_PFX_ARCHLIB} COMPONENT ${QPID_COMPONENT_CLIENT} ) diff --git a/cpp/bindings/qpid/perl/ChangeLog b/cpp/bindings/qpid/perl/ChangeLog new file mode 100644 index 0000000000..72685443b1 --- /dev/null +++ b/cpp/bindings/qpid/perl/ChangeLog @@ -0,0 +1,6 @@ +Version 0.22 (TBA): + * QPID-4466: qpid::messaging::Duration now supports multiplication + * QPID-4416: Messages with embedded nulls won't break on getContentPtr + * QPID-4505: Provides unit tests for Address, Duration and Message + * QPID-4504: Broke up the Per classes into separate source modules + * QPID-4580: Added perldoc markup to each source module diff --git a/cpp/bindings/qpid/perl/LICENSE b/cpp/bindings/qpid/perl/LICENSE new file mode 100644 index 0000000000..bc46b77047 --- /dev/null +++ b/cpp/bindings/qpid/perl/LICENSE @@ -0,0 +1,206 @@ +========================================================================= +== Apache License == +========================================================================= + + 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. + diff --git a/cpp/bindings/qpid/perl/Makefile.PL b/cpp/bindings/qpid/perl/Makefile.PL new file mode 100644 index 0000000000..7a4d7f03dc --- /dev/null +++ b/cpp/bindings/qpid/perl/Makefile.PL @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use strict; + +use ExtUtils::MakeMaker; +use Config; + +WriteMakefile( + NAME => 'cqpid_perl', + PREREQ_PM => {}, + LIBS => ["-lqpidmessaging -lqpidtypes"], + C => ['cqpid_perl.cpp'], +); diff --git a/cpp/bindings/qpid/perl/README b/cpp/bindings/qpid/perl/README new file mode 100644 index 0000000000..ca5a96e539 --- /dev/null +++ b/cpp/bindings/qpid/perl/README @@ -0,0 +1,15 @@ +Qpid Perl Language Bindings +=========================== + +How to get help +=============== + +You can use the perldoc command to display API help for working with Qpid. + + perldoc qpid_messaging.pm + +will show a simple example application written in Perl that uses the APIs. +From there you can display the individual module documentation by typing: + + perldoc [module] + diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Address.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Address.pm new file mode 100644 index 0000000000..d417770b1c --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Address.pm @@ -0,0 +1,338 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Address + +=head1 DESCRIPTION + +An B
represents an address to which messages can be sent or +from which they can be received. + +=head2 THE ADDRESS STRING + +An address can be described suing the following pattern: + +EaddressE [ / EsubjectE ]= ; [ { EkeyE : EvalueE , ... } ] + +where B
is a simple name and B is a subject or subject +pattern. + +=head3 ADDRESS OPTIONS + +The options, encluded in curly braces, are key:value pairs delimited by a comma. +The values can be nested maps also enclosed in curly braces. Or they can be +lists of values, where they are contained within square brackets but still comma +delimited, such as: + + [value1,value2,value3] + +The following are the list of supported options: + +=over + +=item B + +Indicates if the address should be created; values are B, B, +B or B + +=item B + +Indicates whether or not to assert any specified node properties; values are +B, B, B or B + +=item B + +Indicates whether or not to delete the addressed node when a sender or receiver +is cancelled; values are B, B, B or B + +=item B + +A nested map describing properties for the addressed node. Properties are +B (B or B), B (a boolean), B (a nested +map of AMQP 0.10-specific options) and B (a nested list which +specifies a queue, exchange or a binding key and arguments). + +=item B + +=item B + +=back + +=cut + +package qpid::messaging::Address; + +use overload ( + 'bool' => \& boolify, + '""' => \& stringify, + ); + +sub boolify { + my ($self) = @_; + my $impl = $self->{_impl}; + + return length($impl->getName()); +} + +sub stringify { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $self->str(); +} + +sub str { + my ($self) = @_; + + return $self->get_implementation()->str(); +} + +=pod + +=head1 CONSTRUCTOR + +Creates an B
+ +=over + +=item $address = new qpid::messaging::Address( addr ) + +=back + +=head3 ARGUMENTS + +=over + +=item * addr + +The address string. + +=back + +=cut +sub new { + my ($class) = @_; + my ($self) = {}; + + # 2 args: either a string address or a cqpid_perl::Address + # 3+ args: name + subject + options + type + if (@_ eq 2) { + my $address = $_[1]; + + if (ref($address) eq 'cqpid_perl::Address') { + $self->{_impl} = $address; + } else { + $self->{_impl} = new cqpid_perl::Address($_[1]); + } + } elsif (@_ >= 4) { + my $impl = new cqpid_perl::Address($_[1], $_[2], $_[3]); + + $impl->setType($_[4]) if @_ >= 5; + + $self->{_impl} = $impl; + } else { + die "You must specify an address." + } + + bless $self, $class; + return $self; +} + +sub get_implementation { + my ($self) = @_; + return $self->{_impl}; +} + +=pod + +=head1 ATTRIBUTES + +=cut + +=pod + +=head2 NAME + +The name portion of the address. + +=over + +=item $address->set_name( name ) + +=item $name = $address->get_name + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +See the address string explanation. + +=back + +=cut +sub set_name { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setName($_[1]); +} + +sub get_name { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getName(); +} + +=pod + +=head2 SUBJECT + +The subject portion of the address. + +=over + +=item $address->set_subject( subject ) + +=item $subject = $address->get_subject + +=back + +=head3 ARGUMENTS + +=over + +=item * subject + +See the address string explanation. + +=back + +=cut +sub set_subject { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setSubject($_[1]); +} + +sub get_subject { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getSubject; +} + +=pod + +=head2 OPTIONS + +The address options. + +=over + +=item $address->set_options( options ) + +=item @opts = $address->get_options + +=back + +=head3 ARGUMENTS + +=over + +=item * options + +The set of name:value pairs for the address. See the address string explanation. + +=back + +=cut +sub set_options { + my ($self) = @_; + my $impl = $self->{_impl}; + my $options = $_[1]; + + die "Options cannot be null" if !defined($options); + + $impl->setOptions($_[1]); +} + +sub get_options { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getOptions; +} + +=pod + +=head2 TYPE + +The type of the address determines how B and B objects are +constructed for it. It also affects how a b address is encoded. + +If no type is specified then it willb e determined by querying the broker. +Explicitly setting the type prevents this. + +=over + +=item $address->set_type( type ) + +=item $type = $address->get_type + +=back + +=head3 ARGUMENTS + +=over + +=item * type + +Values can be either B or B. + +=back + +=cut +sub set_type { + my ($self) = @_; + my $impl = $self->{_impl}; + my $type = $_[1]; + + die "Type must be defined" if !defined($type); + + $impl->setType($type); +} + +sub get_type { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getType; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Connection.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Connection.pm new file mode 100644 index 0000000000..6d478cdf0c --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Connection.pm @@ -0,0 +1,291 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Connection + +=head1 DESCRIPTION + +A B represents a network connection to a remote +endpoint. + +=cut + +package qpid::messaging::Connection; + +=pod + +=head1 CONSTRUCTOR + +=over + +=item $conn = new qpid::messaging::Connection + +=item $conn = new qpid::messaging::Connection( url ) + +=item $conn = new qpid::messaging::Connection( url, options ) + +Creates a connection object. Raises a C if an invalid +connection option is used. + +=back + +=head3 ARGUMENTS + +=over + +=item * url + +The URL for the broker. See B for more on + address strings + +=item * options + +The connection options. + +=back + +=cut + +sub new { + my ($class) = @_; + my $self = { + _url => $_[1] || "localhost:5672", + _options => $_[2] || {}, + _impl => $_[3], + }; + + bless $self, $class; + return $self; +} + +=pod + +=head1 ACTIONS + +=cut + + +=pod + +=head2 OPENING AND CLOSING CONNECTIONS + +=cut + + +=pod + +=over + +=item $conn->open + +Establishes the connection to the broker. + +=back + +=cut +sub open { + my ($self) = @_; + my $impl = $self->{_impl}; + + # if we have an implementation instance then use it, otherwise + # create a new implementation instance + unless (defined($impl)) { + my $url = $self->{_url}; + my ($options) = $self->{_options}; + + $impl = new cqpid_perl::Connection($url, $options); + $self->{_impl} = $impl + } + + $impl->open() unless $impl->isOpen() +} + +=pod + +=over + +=item $conn->is_open + +Reports whether the connection is open. + +=back + +=cut +sub is_open { + my ($self) = @_; + my $impl = $self->{_impl}; + + if (defined($impl) && $impl->isOpen()) { + 1; + } else { + 0; + } +} + +=pod + +=over + +=item $conn->close + +Closes the connection. + +=back + +=cut +sub close { + my ($self) = @_; + + if ($self->is_open) { + my $impl = $self->{_impl}; + + $impl->close; + $self->{_impl} = undef; + } +} + +=pod + +=head2 SESSIONS + +=cut + + +=pod + +=over + +=item $session = $conn->create_session + +=item $conn->create_session( name ) + +Creates a new session. + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +Specifies a name for the session. + +=back + +=cut +sub create_session { + my ($self) = @_; + + die "No connection available." unless ($self->open); + + my $impl = $self->{_impl}; + my $name = $_[1] || ""; + my $session = $impl->createSession($name); + + return new qpid::messaging::Session($session, $self); +} + +=pod + +=over + +=item $session = $conn->create_transactional_session + +=item $session = $conn->create_transaction_session( name ) + +Creates a transactional session. + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +Specifies a name for the session. + +=back + +=cut +sub create_transactional_session { + my ($self) = @_; + + die "No connection available." unless ($self->open); + + my $impl = $self->{_impl}; + my $name = $_[1] || ""; + my $session = $impl->createTransactionalSession($name); + + return new qpid::messaging::Session($session, $self); +} + +=pod + +=over + +=item $session = $conn->get_session( name ) + +Returns the session with the specified name. + +=over + +=item $name + +The name given to the session when it was created. + +=back + +=back + +=cut +sub get_session { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getSession($_[1]); +} + +=pod + +=over + +=item $uname = $conn->get_authenticated_username + +Returns the username user to authenticate with the broker. + +If the conneciton did not use authentication credentials, then the +username returned is "anonymous". + +=back + +=cut +sub get_authenticated_username { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getAuthenticatedUsername; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Duration.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Duration.pm new file mode 100644 index 0000000000..7d05daeeab --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Duration.pm @@ -0,0 +1,204 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Duration + +=head1 DESCRIPTION + +A B represents a period of time in milliseconds. + +=head1 NAMED DURATIONS + +The following named durations are available as constants + +=over + +=item B + +The maximum wait time, equal to the maximum integer value for the platform. +Effective this will wait forever. + +=item B + +An alias for 0 milliseconds. + +=item B + +An alias for 1,000 milliseconds. + +=item B + +An alias for 60,000 milliseconds. + +=back + +=cut + +package qpid::messaging::Duration; + +=pod + +=head1 OPERATORS + +=cut + +use overload ( + "*" => \&multiply, + "==" => \&equalify, + "!=" => \&unequalify, + ); + +=pod + +=over + +=item $doubled = $duration * $factor + +=item $doubled = $duration * 2 + +Multiplies the duration and returns a new instance. + +=over + +=item $factor + +A factor for multiplying the duration. + +=back + +=back + +=cut +sub multiply { + my ($self) = @_; + my $factor = $_[1]; + + die "Factor must be non-negative values" if !defined($factor) || ($factor < 0); + + my $duration = $self->{_impl} * $factor; + + return new qpid::messaging::Duration($duration); +} + +sub equalify { + my ($self) = @_; + my $that = $_[1]; + + return 0 if !defined($that) || !UNIVERSAL::isa($that, 'qpid::messaging::Duration');; + + return ($self->get_milliseconds() == $that->get_milliseconds()) ? 1 : 0; +} + +sub unequalify { + my ($self) = @_; + my $that = $_[1]; + + return 1 if !defined($that) || !UNIVERSAL::isa($that, 'qpid::messaging::Duration');; + + return ($self->get_milliseconds() != $that->get_milliseconds()) ? 1 : 0; +} + +=pod + +=head1 CONSTRUCTOR + +Creates a new instance. + +=over + +=item duration = new qpid::messaging::Duration( time ) + +=back + +=head3 ARGUMENTS + +=over + +=item * time + +The duration in B. + +=back + +=cut +sub new { + my ($class) = @_; + my $duration = $_[1]; + + die "Duration time period must be defined" if !defined($duration); + + if (!UNIVERSAL::isa($duration, 'cqpid_perl::Duration')) { + die "Duration must be non-negative" if $duration < 0; + $duration = new cqpid_perl::Duration($duration); + } + + my ($self) = { + _impl => $duration, + }; + + bless $self, $class; + return $self; +} + +=pod + +=head1 ATTRIBUTES + +=cut + + +=pod + +=head2 MILLISECONDS + +The length of time is measured in milliseconds. + +=over + +=item time = $duration->get_milliseconds + +=back + +=cut +sub get_milliseconds { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getMilliseconds(); +} + +sub get_implementation { + my ($self) = @_; + + return $self->{_impl}; +} + +# TODO: Need a better way to define FOREVER +use constant { + FOREVER => new qpid::messaging::Duration(1000000), + IMMEDIATE => new qpid::messaging::Duration(0), + SECOND => new qpid::messaging::Duration(1000), + MINUTE => new qpid::messaging::Duration(60000), +}; + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm new file mode 100644 index 0000000000..6437290244 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Message.pm @@ -0,0 +1,584 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Message + +=head1 DESCRIPTION + +A B a routable piece of information. + +=cut + +package qpid::messaging::Message; + + +=pod + +=head1 CONSTRUCTOR + +Creates a B. + +=over + +=item $msg = new qpid::messaging::Message + +=item $msg = new qpid::messaging::Message( $content ) + +=back + +=head3 ARGUMENTS + +=over + +=item * $content + +The message's content. + +=back + +=cut +sub new { + my ($class) = @_; + my $content = $_[1] if (@_ > 1); + my $impl = $_[2] if (@_ > 2); + my ($self) = { + _content => $content || "", + _impl => $impl || undef, + }; + + unless (defined($self->{_impl})) { + my $impl = new cqpid_perl::Message($self->{_content}); + + $self->{_impl} = $impl; + } + + bless $self, $class; + return $self; +} + +sub get_implementation { + my ($self) = @_; + + return $self->{_impl}; +} + + +=pod + +=head1 ATTRIBUTES + +=cut + +=pod + +=head2 REPLY TO ADDRESS + +The reply-to address tells a receiver where to send any responses. + +=over + +=item $msg->set_reply_to( "#reqly-queue;{create:always}" ) + +=item $msg->set_reply_to( address ) + +=item $address = $msg->get_reply_to + +=back + +=head3 ARGUMENTS + +=over + +=item * address + +The address. Can be either an instance of B or else an +address string. + +=back + +=cut +sub set_reply_to { + my ($self) = @_; + my $impl = $self->{_impl}; + my $address = $_[1]; + + # if the address was a string, then wrap it + # in a qpid::messaging::Address instance + if (!UNIVERSAL::isa($address, 'qpid::messaging::Address')) { + $address = new qpid::messaging::Address($_[1]); + } + + $impl->setReplyTo($address->get_implementation()); +} + +sub get_reply_to { + my ($self) = @_; + my $impl = $self->{_impl}; + + return new qpid::messaging::Address($impl->getReplyTo()); +} + +=pod + +=head2 SUBJECT + +=over + +=item $msg->set_subject( "responses" ) + +=item $msg->set_subject( subject ) + +=item $subject = $msg->get_subject + +=back + +=cut +sub set_subject { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setSubject($_[1]); +} + +sub get_subject { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getSubject; +} + +=pod + +=head2 CONTENT TYPE + +This should be set by the sending application and indicates to the +recipients of the message how to interpret or decide the content. + +By default, only dictionaries and maps are automatically given a content +type. If this content type is replaced then retrieving the content will +not behave correctly. + +=over + +=item $msg->set_content_type( content_type ) + +=back + +=head3 ARGUMENTS + +=over + +=item * content_type + +The content type. For a list this would be C and for a hash it is +C. + +=back + +=cut +sub set_content_type { + my ($self) = @_; + my $type = $_[1]; + + my $impl = $self->{_impl}; + $impl->setContentType($type); +} + +sub get_content_type { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getContentType; +} + +=pod + +=head2 MESSAGE ID + +A message id must be a UUID type. A non-UUID value will be converted +to a zero UUID, thouygh a blank ID will be left untouched. + +=over + +=item $msg->set_message_id( id ) + +=item $id = $msg->get_message_id + +=back + +=cut +sub set_message_id { + my ($self) = @_; + my $impl = $self->{_impl}; + my $id = $_[1]; + + die "message id must be defined" if !defined($id); + + $impl->setMessageId($id); +} + +sub get_message_id { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getMessageId; +} + +=pod + +=head2 USER ID + +The user id should, in general, be the user-id which was used when +authenticating the connection itself, as the messaging infrastructure +will verify this. + +See B. + +=over + +=item $msg->set_user_id( id ) + +=item $id = $msg->get_user_id + +=back + +=cut +sub set_user_id { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setUserId($_[1]); +} + +sub get_user_id { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getUserId; +} + +=pod + +=head2 CORRELATION ID + +The correlation id can be used as part of a protocol for message exchange +patterns; e.g., a request-response pattern might require the correlation id +of the request and hte response to match, or it might use the message id of +the request as the correlation id on the response. + +B If the id is not a string then the id is setup using the object's +string representation. + +=over + +=item $msg->set_correlation_id( id ) + +=item $id = $msg->get_correlation_id + +=back + +=cut +sub set_correlation_id { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setCorrelationId($_[1]); +} + +sub get_correlation_id { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getCorrelationId; +} + +=pod + +=head2 PRIORITY + +The priority may be used by the messaging infrastructure to prioritize +delivery of messages with higher priority. + +B If the priority is not an integer type then it is set using the +object's integer represtation. If the integer value is greater than an +8-bit value then only 8-bits are used. + +=over + +=item $msg->set_priority( priority ) + +=item $priority = $msg->get_priority + +=back + +=cut +sub set_priority { + my ($self) = @_; + my $impl = $self->{_impl}; + my $priority = $_[1]; + + die "Priority must be provided" if !defined($priority); + + $priority = int($priority); + die "Priority must be non-negative" if $priority < 0; + + $impl->setPriority($priority); +} + +sub get_priority { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getPriority; +} + +=pod + +=head2 TIME TO LIVE + +This can be used by the messaging infrastructure to discard messages +that are no longer of relevance. + +=over + +=item $msg->set_ttl( ttl ) + +=item $ttl = $msg->get_ttl + +=back + +=head3 ARGUMENTS + +=over + +=item * ttl + +A B instance. If it is not, then a new instance +is created using the integer value for the argument. + +A B value is treated as the equipment of +B. + +=back + +=cut +sub set_ttl { + my ($self) = @_; + my $impl = $self->{_impl}; + my $duration = $_[1]; + + die "Duration must be provided" if !defined($duration); + if (!UNIVERSAL::isa($duration, 'qpid::messaging::Duration')) { + $duration = int($duration); + + if ($duration < 0) { + $duration = qpid::messaging::Duration::FOREVER; + } elsif ($duration == 0) { + $duration = qpid::messaging::Duration::IMMEDIATE; + } else { + $duration = new qpid::messaging::Duration(int($duration)); + } + } + + $impl->setTtl($duration->get_implementation()); +} + +sub get_ttl { + my ($self) = @_; + my $impl = $self->{_impl}; + + return new qpid::messaging::Duration($impl->getTtl); +} + +=pod + +=head2 DURABILITY + +The durability of a B is a hint to the messaging infrastructure that +the message should be persisted or otherwise stored. This helps to ensure that +the message is not lost due to failures or a shutdown. + +=over + +=item $msg->set_durable( 1 ) + +=item $durable = $msg->get_durable + +=back + +=cut +sub set_durable { + my ($self) = @_; + my $impl = $self->{_impl}; + my $durable = $_[1]; + + die "Durable must be specified" if !defined($durable); + + $impl->setDurable($durable); +} + +sub get_durable { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getDurable; +} + +=pod + +=head2 REDELIVERED + +This is a hint to the messaging infrastructure that if de-duplication is +required, that this message should be examined to determine if it is a +duplicate. + +=over + +=item $msg->set_redelivered( 1 ) + +=item $redelivered = $msg->get_redelivered + +=back + +=cut +sub set_redelivered { + my ($self) = @_; + my $impl = $self->{_impl}; + my $redelivered = $_[1]; + + die "Redelivered must be specified" if !defined($redelivered); + + $impl->setRedelivered($redelivered); +} + +sub get_redelivered { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getRedelivered; +} + +=pod + +=head2 PROPERTIES + +Named properties for the message are name/value pairs. + +=over + +=item $msg->set_property( name, value ) + +=item $value = $msg->get_property( name ) + +=item @props = $msg->get_properties + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +The property name. + +=item * value + +The property value. + +=back + +=cut +sub set_property { + my ($self) = @_; + my $impl = $self->{_impl}; + my $key = $_[1]; + my $value = $_[2]; + + $impl->setProperty($key, $value); +} + +sub get_properties { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getProperties; +} + +=pod + +=head2 CONTENT + +The message content. + +=begin _private + +TODO: Need to make the content automatically encode and decode for +hashes and lists. + +=end _private + +=over + +=item $msg->set_content( content ) + +=item $content = $msg->get_content + +=item $length = $msg->get_content_size + +=back + +=cut +sub set_content { + my ($self) = @_; + my $content = $_[1]; + my $impl = $self->{_impl}; + + die "Content must be provided" if !defined($content); + + $self->{_content} = $content; + + qpid::messaging::encode($content, $self); +} + +sub get_content { + my ($self) = @_; + my $impl = $self->{_impl}; + $content = $self->{_content} || undef; + + if(!defined($content)) { + $content = qpid::messaging::decode($self); + $self->{_content} = $content; + } + + return $content; +} + +sub get_content_size { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getContentSize; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Receiver.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Receiver.pm new file mode 100644 index 0000000000..c3bc4bb8a8 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Receiver.pm @@ -0,0 +1,317 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Receiver + +=head1 DESCRIPTION + +A B is the entity though which messages are received. + +An instance can only be created using an active (i.e., not previously closed) +B. + +=head1 EXAMPLE + + # create a connection and a session + my $conn = new qpid::messaging::Connection("mybroker:5672"); + conn->open; + my $session = $conn->create_session; + + # create a receiver that listens on the "updates" topic of "alerts" + my $recv = $session->create_receiver("alerts/updates"); + + # set the local queue size to hold a maximum of 100 messages + $recv->set_capacity(100); + + # wait for an incoming message and process it + my $incoming = $recv->get; + process($incoming) + +=cut + +package qpid::messaging::Receiver; + +sub new { + my ($class) = @_; + my ($self) = { + _impl => $_[1], + _session => $_[2], + }; + + die "Must provide an implementation." unless defined($self->{_impl}); + die "Must provide a Session." unless defined($self->{_session}); + + bless $self, $class; + return $self; +} + +=pod + +=head1 ACTIONS + +=cut + + +=pod + +There are two ways to retrieve messages: from the local queue or from the +remote queue. + +=head2 GETTING FROM THE LOCAL QUEUE + +Messages can be held locally in message queues. + +=over + +=item $incoming = $receiver->get + +=item $incoming = $receiver->get( timeout) + +=back + +=head3 ARGUMENTS + +=over + +=item * timeout + +The period of time to wait for a message before raising an exception. If no +period of time is specified then the default is to wait B. + +=back + +=cut +sub get { + my ($self) = @_; + my $duration = $_[1]; + my $impl = $self->{_impl}; + + $duration = $duration->get_implementation() if defined($duration); + + my $message = undef; + + if (defined($duration)) { + $message = $impl->get($duration); + } else { + $message = $impl->get; + } +} + +=pod + +=head2 FETCHING FROM THE REMOTE QUEUE + +Messages held in the remote queue must be fetched from the broker in order +to be processed. + +=over + +=item $incoming = $receiver->fetch + +=item $incoming = $receiver->fetch( time ) + +=back + +=head3 ARGUMENTS + +=over + +=item * timeout + +The period of time to wait for a message before raising an exception. If no +period of time is specified then the default is to wait B. + +=back + +=cut +sub fetch { + my ($self) = @_; + my $duration = $_[1]; + my $impl = $self->{_impl}; + my $message = undef; + + if (defined($duration)) { + $message = $impl->fetch($duration->get_implementation()); + } else { + $message = $impl->fetch; + } + + return new qpid::messaging::Message("", $message); +} + +=pod + +=head2 CLOSING THE RECEIVER + +=over + +=item receiver->close + +Closes the receiver. + +=back + +=cut +sub close { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->close; +} + +=pod + +=head1 ATTRIBUTES + +=cut + + +=pod + +=head2 CAPACITY + +The maximum number of messages that are prefected and held locally is +determined by the capacity of the receiver. + +=over + +=item $receiver->set_capacity( size ) + +=item $size = $receiver->get_capacity + +=back + +=cut +sub set_capacity { + my ($self) = @_; + my $capacity = $_[1]; + my $impl = $self->{_impl}; + + $impl->setCapacity($capacity); +} + +sub get_capacity { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getCapacity; +} + +=pod + +=head2 AVAILABLE + +The number of messages waiting in the local queue. + +The value is always in the range 0 <= B <= B. + +=over + +=item $count = $receiver->get_available + +=back + +=cut + +sub get_available { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getAvailable; +} + +=pod + +=over + +=item $count = $receiver->get_unsettled + +Returns the number of messages that have been received and acknowledged but +whose acknowledgements have not been confirmed by the sender. + +=back + +=cut +sub get_unsettled { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getUnsettled; +} + +=pod + +=over + +=item $name = $receiver->get_name + +Returns the name of the receiver. + +=back + +=cut +sub get_name { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getName; +} + +=pod + +=over + +=item $session = $receiver->get_session + +Returns the B instance from which this +receiver was created. + +=back + +=cut +sub get_session { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->{_session}; +} + +=pod + +=over + +=item $receiver->is_closed + +Returns whether the receiver is closed. + +=back + +=cut +sub is_closed { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->isClosed; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Sender.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Sender.pm new file mode 100644 index 0000000000..5d0896ff79 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Sender.pm @@ -0,0 +1,258 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Sender + +=head1 DESCRIPTION + +A B is the entity through which messages are sent. + +An instance can only be created using an active (i.e., not previously closed) +B. + +=head1 EXAMPLE + + # create a connection and a session + my $conn = new qpid::messaging::Connection("mybroker:5672"); + conn->open; + my $session = $conn->create_session; + + # create a sender that posts messages to the "updates" queue + my $sender = $session->create_sender "updates;{create:always}" + + # begin sending updates + while( 1 ) { + my $content = wait_for_event; + $sender->send(new qpid::messaging::Message($content)); + } + +=cut + +package qpid::messaging::Sender; + +sub new { + my ($class) = @_; + my ($self) = { + _impl => $_[1], + _session => $_[2], + }; + + die "Must provide an implementation." unless defined($self->{_impl}); + die "Must provide a Session." unless defined($self->{_session}); + + bless $self, $class; + return $self; +} + +=pod + +=head1 ACTIONS + +=cut + + +=pod + +=head2 SENDING MESSAGES + +=over + +=item $sender->send( message ) + +=item $sender->send( message, block) + +Sends a message, optionally blocking until the message is received by +the broker. + +=back + +=head3 ARGUMENTS + +=over + +=item * message + +The message to be sent. + +=item * block + +If true then blocks until the message is received. + +=back + +=cut +sub send { + my ($self) = @_; + my $message = $_[1]; + my $sync = $_[2] || 0; + + die "No message to send." unless defined($message); + + my $impl = $self->{_impl}; + + $impl->send($message->get_implementation, $sync); +} + +=pod + +=head2 CLOSING THE SENDER + +=item sender->close + +Closes the sender. + +This does not affect the ownering B or B + +=back + +=cut +sub close { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->close; +} + +=pod + +=head1 ATTRIBUTES + +=cut + +=pod + +=head2 CAPACITY + +The capacity is the number of outoing messages that can be held pending +confirmation of receipt by the broker. + +=over + +=item sender->set_capacity( size ) + +=item $size = sender->get_capacity + +=back + +=back + +=cut +sub set_capacity { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->setCapacity($_[1]); +} + +sub get_capacity { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getCapacity; +} + +=pod + +=head2 UNSETTLED + +The number of messages sent that are pending receipt confirmation by the broker. + +=over + +=item $count = sender->get_unsettled + +=back + +=cut +sub get_unsettled { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getUnsettled; +} + +=pod + +=head2 AVAILABLE + +The available slots for sending messages. + +This differences form B in that it is the available slots in the +senders capacity for holding outgoing messages. The difference between +capacity and available is the number of messages that have no been delivered +yet. + +=over + +=item $slots = sender->get_available + +=back + +=cut +sub get_available { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getAvailable(); +} + +=pod + +=head2 NAME + +The human-readable name for this sender. + +=over + +=item $name = sender-get_name + +=back + +=cut +sub get_name { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getName; +} + +=pod + +=head2 SESSION + +The owning session from which the sender was created. + +=over + +=item $session = $sender->get_session + +=back + +=cut +sub get_session { + my ($self) = @_; + + return $self->{_session}; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/Session.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/Session.pm new file mode 100644 index 0000000000..af85731685 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/Session.pm @@ -0,0 +1,473 @@ +# +# 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. +# + +=pod + +=head1 NAME + +qpid::messaging::Session + +=head1 DESCRIPTION + +A B represents a distinct conversation between end +points. They are created from an active (i.e, not closed) B. + +A session is used to acknowledge individual or all messages that have +passed through it, as well as for creating senders and receivers for conversing. +=cut +package qpid::messaging::Session; + +sub new { + my ($class) = @_; + my ($self) = { + _impl => $_[1], + _conn => $_[2], + }; + + die "Must provide an implementation." unless defined($self->{_impl}); + die "Must provide a Connection." unless defined($self->{_conn}); + + bless $self, $class; + return $self; +} + +=pod + +=head1 ACTIONS + +=cut + + +=pod + +=head2 CLOSING THE SESSION + +=over + +=item $session->close + +=back + +=cut +sub close { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->close; +} + +=pod + +=head2 TRANSACTIONS + +Transactions can be rolled back or committed. + +=over + +=item $session->commit + +=item $session->rollback + +=back + +=cut +sub commit { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->commit; +} + +sub rollback { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->rollback; +} + +=pod + +=head2 MESSAGE DISPOSITIONS + +=cut + + +=pod + +=over + +=item $session->acknowledge( msg ) + +Acknowledges that a specific message that has been received. + +=back + +=begin _private + +TODO: How to handle acknowledging a specific message? + +=end _private + +=cut +sub acknowledge { + my ($self) = @_; + my $sync = $_[1] || 0; + + my $impl = $self->{_impl}; + + $impl->acknowledge($sync); +} + +=pod + +=over + +=item $session->reject( msg ) + +Rejects the specified message. A reject message will not be redelivered. + +=back + +=cut +sub reject { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->reject($_[1]); +} + +=pod + +=over + +=item $session->release( msg ) + +Releases the specified message, which allows the broker to attempt to +redeliver it. + +=back + +=cut +sub release { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->release($_[1]); +} + +=pod + +=over + +=item $session->sync + +=item $session->sync( block ) + +Requests synchronization with the broker. + +=back + +=head3 ARGUMENTS + +=over + +=item * block + +If true, then the call blocks until the process completes. + +=back + +=cut +sub sync { + my ($self) = @_; + my $impl = $self->{_impl}; + + if(defined($_[1])) { + $impl->sync($_[1]); + } else { + $impl->sync; + } +} + +=pod + +=head2 SENDERS AND RECEIVERS + +=cut + + +=pod + +=over + +=item $sender = $session->create_sender( address ) + +Creates a new sender. + +=back + +=head3 ARGUMENTS + +=over + +=item * address + +The sender address. See B for more details + +=back + +=cut +sub create_sender { + my ($self) = @_; + my $impl = $self->{_impl}; + + my $address = $_[1]; + + if (ref($address) eq "qpid::messaging::Address") { + my $temp = $address->get_implementation(); + $address = $temp; + } + my $send_impl = $impl->createSender($address); + + return new qpid::messaging::Sender($send_impl, $self); +} + +=pod + +=over + +=item $sender = $session->get_session( name ) + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +The name of the sender. + +Raises an exception when no sender with that name exists. + +=back + +=cut +sub get_sender { + my ($self) = @_; + my $impl = $self->{_impl}; + + my $send_impl = $impl->getSender($_[1]); + my $sender = undef; + + if (defined($send_impl)) { + $sender = new qpid::messaging::Sender($send_impl, $self); + } + + return $sender; +} + +=pod + +=over + +=item $receiver = $session->create_receiver( address ) + +=back + +=head3 ARGUMENTS + +=over + +=item * address + +The receiver address. see B for more details. + +=back + +=cut +sub create_receiver { + my ($self) = @_; + my $impl = $self->{_impl}; + + my $address = $_[1]; + + if (ref($address) eq "qpid::messaging::Address") { + $address = $address->get_implementation(); + } + my $recv_impl = $impl->createReceiver($address); + + return new qpid::messaging::Receiver($recv_impl, $self); +} + +=pod + +=over + +=item $receiver = $session->get_receiver( name ) + +=back + +=head3 ARGUMENTS + +=over + +=item * name + +The name of the receiver. + +=back + +=cut +sub get_receiver { + my ($self) = @_; + my $impl = $self->{_impl}; + + my $recv_impl = $impl->getReceiver($_[1]); + my $receiver = undef; + + if (defined($recv_impl)) { + $receiver = new qpid::messaging::Receiver($recv_impl, $self); + } + + return $receiver; +} + +=pod + +=head1 ATTRIBUTES + +=cut + + +=pod + +=head2 RECEIVABLE + +The total number of receivable messages, and messages already received, +by receivers associated with this session. + +=over + +=item $session->get_receivable + +=back + +=cut +sub get_receivable { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getReceivable; +} + +=pod + +=head2 UNSETTLED ACKNOWLEDGEMENTS + +The number of messages that have been acknowledged by this session whose +acknowledgements have not been confirmed as processed by the broker. + +=over + +=item $session->get_unsettled_acks + +=back + +=cut +sub get_unsettled_acks { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->getUnsettledAcks; +} + +=pod + +=head2 NEXT RECEIVER + +The next receiver is the one, created by this session, that has any pending +local messages. + +If no receivers are found within the timeout then a B is +raised. + +=over + +=item $session->get_next_receiver + +=item $session->get_next_receiver( timeout ) + +=back + +=head3 ARGUMENTS + +=over + +=item * timeout + +The period of time to wait for a receiver to be found. If no period of time is +specified then the default is to wait B. + +=back + +=cut +sub get_next_receiver { + my ($self) = @_; + my $impl = $self->{_impl}; + + my $timeout = $_[1] || qpid::messaging::Duration::FOREVER; + + return $impl->getNextReceiver($timeout); +} + +=pod + +=head2 CONNECTION + +=over + +=item $conn = $session->get_connection + +Returns the owning connection for the session. + +=back + +=cut +sub get_connection { + my ($self) = @_; + + return $self->{_conn}; +} + +sub has_error { + my ($self) = @_; + my $impl = $self->{_impl}; + + return $impl->hasError; +} + +sub check_for_error { + my ($self) = @_; + my $impl = $self->{_impl}; + + $impl->checkForError; +} + +1; diff --git a/cpp/bindings/qpid/perl/lib/qpid/messaging/codec.pm b/cpp/bindings/qpid/perl/lib/qpid/messaging/codec.pm new file mode 100644 index 0000000000..c9d6845eb9 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid/messaging/codec.pm @@ -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. +# + +package qpid::messaging; + +sub encode { + my $content = $_[0]; + my $message = $_[1]; + my $impl = $message->get_implementation(); + + if(UNIVERSAL::isa($content, "HASH")) { + cqpid_perl::encode($content, $impl, "amqp/map"); + } elsif(UNIVERSAL::isa($content, "ARRAY")) { + cqpid_perl::encode($content, $impl, "amqp/list"); + } else { + $message->get_implementation()->setContent($content); + } +} + +sub decode { + my $message = $_[0]; + my $impl = $message->get_implementation(); + my $content_type = $impl->getContentType(); + + if($content_type eq "amqp/map") { + $result = cqpid_perl::decodeMap($impl); + } elsif($content_type eq "amqp/list") { + $result = cqpid_perl::decodeList($impl); + } else { + $result = $impl->getContent(); + } + + return $result; +} + +1; + diff --git a/cpp/bindings/qpid/perl/lib/qpid_messaging.pm b/cpp/bindings/qpid/perl/lib/qpid_messaging.pm new file mode 100644 index 0000000000..e6a2681c15 --- /dev/null +++ b/cpp/bindings/qpid/perl/lib/qpid_messaging.pm @@ -0,0 +1,95 @@ +# +# 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. +# + +use strict; +use warnings; +use cqpid_perl; + +package qpid::messaging; + +use qpid::messaging::codec; +use qpid::messaging::Address; +use qpid::messaging::Duration; +use qpid::messaging::Message; +use qpid::messaging::Receiver; +use qpid::messaging::Sender; +use qpid::messaging::Session; +use qpid::messaging::Connection; + +1; + +__END__ + +=pod + +=head1 NAME + +qpid::messaging + +=head1 DESCRIPTION + +The Qpid Messaging framework is an enterprise messaging framework +based on the open-source AMQP protocol. + +=head1 EXAMPLE + +Here is a simple example application. It creates a link to a broker located +on a system named C. It then creates a new messaging +queue named C and publishes a message to it. It then consumes +that same message and closes the connection. + + use strict; + use warnings; + + use qpid; + + # create a connection, open it and then create a session named "session1" + my $conn = new qpid::messaging::Connection("broker.myqpiddomain.com"); + $conn->open(); + my $session = $conn->create_session("session1"); + + # create a sender and a receiver + # the sender marks the queue as one that is deleted when the sender disconnects + my $send = $session->create_sender("qpid-examples;{create:always}"); + my $recv = $session->create_receiver("qpid-examples"); + + # create an outgoing message and send it + my $outgoing = new qpid::messaging::Message(); + $outgoing->set_content("The time is " . localtime(time)"); + $send->send($outgoing); + + # set the receiver's capacity to 10 and then check out many messages are pending + $recv->set_capacity(10); + print "There are " . $recv->get_available . " messages waiting.\n"; + + # get the nextwaitingmessage, which should be in the local queue now, + # and output the contents + my $incoming = $recv->fetch(); + print "Received the following message: " . $incoming->get_content() . "\n"; + # the output should be the text that was sent earlier + + # acknowledge the message, letting the sender know the message was received + printf "The sender currently has " . $send->get_unsettled . " message(s) pending.\n"; + # should report 1 unsettled message + $session->acknowledge(); # acknowledges all pending messages + print "Now sender currently has " . $send->get_unsettled . " message(s) pending.\n"; + # should report 0 unsettled messages + + # close the connection + $conn->close diff --git a/cpp/bindings/qpid/perl/perl.i b/cpp/bindings/qpid/perl/perl.i index 38ac91761f..0d118ae0fb 100644 --- a/cpp/bindings/qpid/perl/perl.i +++ b/cpp/bindings/qpid/perl/perl.i @@ -19,7 +19,7 @@ %module cqpid_perl %include "std_string.i" -%include "../../swig_perl_typemaps.i" +%include "qpid/swig_perl_typemaps.i" /* Define the general-purpose exception handling */ %exception { @@ -31,5 +31,5 @@ } } -%include "../qpid.i" +%include "qpid/qpid.i" diff --git a/cpp/bindings/qpid/perl/qpid.pm b/cpp/bindings/qpid/perl/qpid.pm new file mode 100644 index 0000000000..88b98353a8 --- /dev/null +++ b/cpp/bindings/qpid/perl/qpid.pm @@ -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. +# + +use qpid_messaging; + +1; diff --git a/cpp/bindings/qpid/perl/t/Address.t b/cpp/bindings/qpid/perl/t/Address.t new file mode 100644 index 0000000000..4e74f8cad2 --- /dev/null +++ b/cpp/bindings/qpid/perl/t/Address.t @@ -0,0 +1,102 @@ +#!/usr/bin/env perl -w +# +# 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. +# + +use Test::More qw(no_plan); +use Test::Exception; + +require 'utils.pm'; + +# verify that qpid is available +BEGIN { use_ok( 'qpid' ); } +require_ok ('qpid' ); + +# construction +# address cannot be null +dies_ok (sub {new qpid::messaging::Address(undef);}, + "Address cannot be null"); + +# can use an address +my $address = new qpid::messaging::Address("0.0.0.0"); +ok ($address, "Can be created with an arbitrary address"); + +# name +# name cannot be null +dies_ok (sub {$address->set_name(undef);}, + "Name cannot be null"); + +# name can be an empty string +$address->set_name(""); +ok ($address->get_name() eq "", + "Name can be empty"); + +# name can be an arbitrary string +my $name = random_string(25); +$address->set_name($name); +ok ($address->get_name() eq $name, + "Name can be an arbitrary string"); + +# subject +# cannot be null +dies_ok (sub {$address->set_subject(undef);}, + "Subject cannot be null"); + +# can be an empty string +$address->set_subject(""); +ok ($address->get_subject() eq "", + "Subject can be empty"); + +# can be an arbitrary string +my $subject = random_string(64); +$address->set_subject($subject); +ok ($address->get_subject() eq $subject, + "Subject can be an arbitrary string"); + +# options +# options cannot be null +dies_ok (sub {$address->set_options(undef);}, + "Options cannot be null"); + +# options can be an empty hash +$address->set_options({}); +ok (eq_hash($address->get_options(), {}), + "Options can be an empty hash"); + +# options cannot be arbitrary values +my %options = ("create", "always", "delete", "always"); +$address->set_options(\%options); +ok (eq_hash($address->get_options(), \%options), + "Options can be arbitrary keys"); + +# type +# cannot be null +dies_ok (sub {$address->set_type(undef);}, + "Type cannot be null"); + +# can be an empty string +$address->set_type(""); +ok ($address->get_type() eq "", + "Type can be an empty string"); + +# can be an arbitrary string +my $type = random_string(16); +$address->set_type($type); +ok ($address->get_type() eq $type, + "Type can be an arbitrary type"); + diff --git a/cpp/bindings/qpid/perl/t/Duration.t b/cpp/bindings/qpid/perl/t/Duration.t new file mode 100644 index 0000000000..6975e8006f --- /dev/null +++ b/cpp/bindings/qpid/perl/t/Duration.t @@ -0,0 +1,124 @@ +#!/usr/bin/env perl -w +# +# 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. +# + +use Test::More qw(no_plan); +use Test::Exception; + +require 'utils.pm'; + +# verify that qpid is available +BEGIN { use_ok( 'qpid' ); } +require_ok ('qpid' ); + +# milliseconds +# duration cannot be null +{ + dies_ok (sub {new qpid::messaging::Duration(undef);}, + "Durations cannot have null time periods"); +} + +# duration cannot be negative +{ + my $period = 0 - (int(rand(65535)) + 1); + dies_ok(sub {new qpid::messaging::Duration($period);}, + "Duration times cannot be negative"); +} + +# duration can be an arbitrary value +{ + my $period = int(rand(65535)); + my $duration = new qpid::messaging::Duration($period); + ok ($duration->get_milliseconds() == $period, + "Milliseconds are properly stored and fetched"); +} + +# multiplier +# cannot multiply by null +dies_ok(sub {qpid::messaging::Duration::FOREVER * undef;}, + "Cannot multiply a duration times a null"); + +# cannot multiply by a negative +dies_ok (sub {qpid::messaging::Duration::MINUTE * -2;}, + "Duration cannot be multiplied by a negative"); + +# multiply by zero returns a zero time period +{ + my $result = qpid::messaging::Duration::MINUTE * 0; + + ok ($result->get_milliseconds() == 0, + "Multiplying duration by 0 returns a 0 duration"); +} + +# multiply by arbitrary values works +{ + my $factor = int(1 + rand(100)); + my $result = qpid::messaging::Duration::MINUTE * $factor; + ok ($result->get_milliseconds() == 60000 * $factor, + "Multiplying by a factor returns a new Duration with that period"); +} + +# equality +# always fails with null +ok (!(qpid::messaging::Duration::MINUTE == undef), + "Duration is never equal to null"); + +# never equal to a non-duration class +ok (!(qpid::messaging::Duration::MINUTE == random_string(12)), + "Duration is never equal to a non-Duration"); + +# works with self +ok (qpid::messaging::Duration::MINUTE == qpid::messaging::Duration::MINUTE, + "Duration is always equal to itself"); + +# fails with non-equal instance +ok (!(qpid::messaging::Duration::MINUTE == qpid::messaging::Duration::SECOND), + "Duration non-equality works"); + +# works with equal instance +{ + my $result = qpid::messaging::Duration::MINUTE * 0; + ok ($result == qpid::messaging::Duration::IMMEDIATE, + "Equality comparison works correctly"); +} + +# non-equality +# always not equal to null +ok (qpid::messaging::Duration::MINUTE != undef, + "Always unequal to null"); + +# always not equal to a non-duration class +ok (qpid::messaging::Duration::MINUTE != random_string(64), + "Always unequal to a non-duration class"); + +# not unequal to itself +ok (!(qpid::messaging::Duration::MINUTE != qpid::messaging::Duration::MINUTE), + "Never unequal to itself"); + +# not unequal to an equal instance +{ + my $duration = qpid::messaging::Duration::MINUTE * 1; + ok (!(qpid::messaging::Duration::MINUTE != $duration), + "Never unequal to an equal instance"); +} + +# works with unequal instances +ok (qpid::messaging::Duration::MINUTE != qpid::messaging::Duration::FOREVER, + "Always unequal to a non-equal instance"); + diff --git a/cpp/bindings/qpid/perl/t/Message.t b/cpp/bindings/qpid/perl/t/Message.t new file mode 100644 index 0000000000..15baafb446 --- /dev/null +++ b/cpp/bindings/qpid/perl/t/Message.t @@ -0,0 +1,286 @@ +#!/usr/bin/env perl -w +# +# 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. +# + +use Test::More qw(no_plan); +use Test::Exception; + +require 'utils.pm'; + +# verify that qpid is available +BEGIN { use_ok( 'qpid' ); } +require_ok ('qpid' ); + +# Create a new message +my $message = new qpid::messaging::Message(); +isa_ok($message, 'qpid::messaging::Message'); + +# reply to +# rejects an null address +dies_ok (sub {$message->set_reply_to(undef);}, + "Reply to cannot be null."); + +# can handle a string address +$message->set_reply_to("test"); +ok ($message->get_reply_to()->str() eq "test", + "Reply to can be set"); + +# subject +# cannot have an null subject +dies_ok (sub {$message->set_subject(undef);}, + "Subject cannot be null"); + +# can have an empty subject +$message->set_subject(""); +ok ($message->get_subject() eq "", + "Subject can be empty"); + +# can have a subject +my $subject = random_string(16); +$message->set_subject($subject); +ok ($message->get_subject() eq $subject, + "Subject can be set."); + +# content type +# cannot have an null content type +dies_ok (sub {$message->set_content_type(undef);}, + "Content type must be defined."); + +# can an empty content type +$message->set_content_type(""); +ok ($message->get_content_type() eq "", + "Content type can be empty"); + +# can have an arbitrary content type +my $content_type = random_string(10); +$message->set_content_type($content_type); +ok ($message->get_content_type() eq $content_type, + "Content type can be arbitrary"); + +# can be for a map +$content_type = "amqp/map"; +$message->set_content_type($content_type); +ok ($message->get_content_type() eq $content_type, + "Content type can be for a map"); + +# message id +# cannot be null +dies_ok (sub {$message->set_message_id(undef);}, + "Message id cannot be null"); + +# can be an empty string +$message->set_message_id(""); +ok ($message->get_message_id() eq "", + "Message id can be empty"); + +# can be an arbitrary string +my $id = random_string(32); +$message->set_message_id($id); +ok ($message->get_message_id() eq $id, + "Message id can be an arbitrary string"); + +# can be a UUID +$id = generate_uuid(); +$message->set_message_id($id); +ok ($message->get_message_id() eq $id, + "Message id can be a valid UUID"); + +# user id +# cannot be null +dies_ok (sub {$message->set_user_id(undef);}, + "User id cannot be null"); + +# can be an empty string +my $user_id = ""; +$message->set_user_id($user_id); +ok ($message->get_user_id() eq $user_id, + "User id can be empty"); + +# can be an arbitrary string +$id = random_string(65); +$message->set_user_id($user_id); +ok ($message->get_user_id() eq $user_id, + "User id can be an arbitrary string"); + +# correlation id +# cannot be null +dies_ok (sub {$message->set_correlation_id(undef);}, + "Correlation id cannot be null"); + +# can be empty +my $correlation_id = ""; +$message->set_correlation_id($correlation_id); +ok ($message->get_correlation_id() eq $correlation_id, + "Correlation id can be an empty string"); + +# can be an arbitrary string +$correlation_id = random_string(32); +$message->set_correlation_id($correlation_id); +ok ($message->get_correlation_id() eq $correlation_id, + "Correlation id can be an arbitrary string"); + +# priority +# cannot be nul +dies_ok (sub {$message->set_priority(undef);}, + "Priority cannot be null"); + +# cannot be negative +my $priority = 0 - (rand(2**8) + 1); +dies_ok (sub {$message->set_priority($priority);}, + "Priority cannot be negative"); + +# can be 0 +$message->set_priority(0); +ok ($message->get_priority() == 0, + "Priority can be zero"); + +# can be an arbitrary value +$priority = int(rand(2**8) + 1); +$message->set_priority($priority); +ok ($message->get_priority() == $priority, + "Priority can be any positive value"); + +# ttl +# cannot be null +dies_ok (sub {$message->set_ttl(undef);}, + "TTL cannot be null"); + +# can be a duration +$message->set_ttl(qpid::messaging::Duration::FOREVER); +ok ($message->get_ttl()->get_milliseconds() == qpid::messaging::Duration::FOREVER->get_milliseconds(), + "TTL can be a Duration"); + +# if numeric, is converted to a duration +my $duration = rand(65535); +$message->set_ttl($duration); +ok ($message->get_ttl()->get_milliseconds() == int($duration), + "TTL can be any arbitrary duration"); + +# if 0 it's converted to IMMEDIATE +$message->set_ttl(0); +ok ($message->get_ttl()->get_milliseconds() == qpid::messaging::Duration::IMMEDIATE->get_milliseconds(), + "TTL of 0 is converted to IMMEDIATE"); + +# if negative it's converted to FOREVER +$message->set_ttl(0 - (rand(65535) + 1)); +ok ($message->get_ttl()->get_milliseconds() == qpid::messaging::Duration::FOREVER->get_milliseconds(), + "TTL of <0 is converted to FOREVER"); + +# durable +# cannot be null +dies_ok (sub {$message->set_durable(undef);}, + "Durable cannot be null"); + +# can be set to true +$message->set_durable(1); +ok ($message->get_durable(), + "Durable can be true"); + +# can be set to false +$message->set_durable(0); +ok (!$message->get_durable(), + "Durable can be false"); + +# redelivered +# redelivered cannot be null +dies_ok (sub {$message->set_redelivered(undef);}, + "Redelivered cannot be null"); + +# can be set to true +$message->set_redelivered(1); +ok ($message->get_redelivered(), + "Redelivered can be true"); + +# can be set to false +$message->set_redelivered(0); +ok (!$message->get_redelivered(), + "Redelivered can be false"); + +# properties +# can retrieve all properties +my $properties = $message->get_properties(); +ok (UNIVERSAL::isa($properties, 'HASH'), + "Returns the properties as a hash map"); + +# property +# setting a property using a null key fails +dies_ok (sub {$message->set_property(undef, "bar");}, + "Property cannot have a null key"); + +# setting a property with a null value succeeds +my $key = random_string(16); +$message->set_property($key, undef); +ok (!$message->get_properties()->{$key}, + "Properties can have null values"); + +# setting a property succeeds +my $value = random_string(255); +$message->set_property($key, $value); +ok ($message->get_properties()->{$key} eq $value, + "Messages can have arbitrary property values"); + +# content +# cannot be null +dies_ok (sub {$message->set_content(undef);}, + "Content cannot be null"); + +# can be an empty string +$message->set_content(""); +ok ($message->get_content() eq "", + "Content can be an empty string"); + +# can be an arbitrary string +my $content = random_string(255); +$message->set_content($content); +ok ($message->get_content() eq $content, + "Content can be an arbitrary string"); + +# Embedded nulls should be handled properly +$content = { id => 1234, name => "With\x00null" }; +qpid::messaging::encode($content, $message); +my $map = qpid::messaging::decode_map($message); +ok ($map->{name} eq "With\x00null", + "Nulls embedded in map values work."); + +# Unicode strings shouldn't be broken +$content = { id => 1234, name => "Euro=\x{20AC}" }; +qpid::messaging::encode($content, $message); +$map = qpid::messaging::decode_map($message); +ok ($map->{name} eq "Euro=\x{20AC}", + "Unicode strings encoded correctly."); + +# Setting the content as a hash automatically encodes it +($content) = {"id" => "1234", "name" => "qpid"}; +$message->set_content($content); +ok ($message->get_content_type() eq "amqp/map", + "Hashes are automatically encoded correctly"); + +# Setting the content as a list automatically encodes it +my @acontent = (1, 2, 3, 4); +$message->set_content(\@acontent); +ok ($message->get_content_type() eq "amqp/list", + "Lists are automatically encoded correctly"); + +# content size +# content size is correct +my $content_size = int(rand(256)); +$content = random_string($content_size); +$message->set_content($content); +ok ($message->get_content_size() == $content_size, + "Content size is correct"); diff --git a/cpp/bindings/qpid/perl/t/utils.pm b/cpp/bindings/qpid/perl/t/utils.pm new file mode 100644 index 0000000000..db8093d324 --- /dev/null +++ b/cpp/bindings/qpid/perl/t/utils.pm @@ -0,0 +1,38 @@ +# 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. +# + +use Digest::MD5; + +sub random_string +{ + my $len=$_[0]; + my @chars=('a'..'z','A'..'Z','0'..'9','_'); + my $result; + + foreach (1..$len) { + $result .= $chars[rand @chars]; + } + return $result; +} + +sub generate_uuid +{ + return Digest::MD5::md5_base64( rand ); +} + +1; diff --git a/cpp/bindings/qpid/python/CMakeLists.txt b/cpp/bindings/qpid/python/CMakeLists.txt index 9cb40162a5..2693475dea 100644 --- a/cpp/bindings/qpid/python/CMakeLists.txt +++ b/cpp/bindings/qpid/python/CMakeLists.txt @@ -21,17 +21,20 @@ ## Use Swig to generate a literal binding to the C++ API ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES CPLUSPLUS ON) -set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i + PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include;-I${qpid-cpp_SOURCE_DIR}/bindings") swig_add_module(cqpid_python python ${CMAKE_CURRENT_SOURCE_DIR}/python.i) swig_link_libraries(cqpid_python qpidmessaging qpidtypes qmf2 ${PYTHON_LIBRARIES}) -set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${PYTHON_INCLUDE_PATH} -I${qpid-cpp_SOURCE_DIR}/include") +set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing") +include_directories(${PYTHON_INCLUDE_PATH} + ${qpid-cpp_SOURCE_DIR}/include + ${qpid-cpp_SOURCE_DIR}/bindings) ##------------------------------------ ## Install the complete Python binding ##------------------------------------ -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cqpid.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cqpid.py @@ -39,12 +42,12 @@ install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cqpi install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cqpid.py ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyc ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyo - DESTINATION ${PYTHON_SITE_PACKAGES} + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/_cqpid_python.so RENAME _cqpid.so - DESTINATION ${PYTHON_SITE_PACKAGES} + DESTINATION ${PYTHON_SITEARCH_PACKAGES} COMPONENT ${QPID_COMPONENT_CLIENT} ) diff --git a/cpp/bindings/qpid/python/Makefile.am b/cpp/bindings/qpid/python/Makefile.am index 432fe7e764..d27cc8b3a2 100644 --- a/cpp/bindings/qpid/python/Makefile.am +++ b/cpp/bindings/qpid/python/Makefile.am @@ -19,7 +19,7 @@ if HAVE_PYTHON_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src/qmf -I$(top_srcdir)/src -I$(top_builddir)/src +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/bindings -I$(top_builddir)/include -I$(top_srcdir)/src/qmf -I$(top_srcdir)/src -I$(top_builddir)/src generated_file_list = \ cqpid.cpp \ @@ -29,7 +29,7 @@ EXTRA_DIST = CMakeLists.txt python.i BUILT_SOURCES = $(generated_file_list) SWIG_FLAGS = -w362,401 -$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qpid.i $(srcdir)/../../swig_python_typemaps.i +$(generated_file_list): $(srcdir)/python.i $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o cqpid.cpp $(srcdir)/python.i pylibdir = $(pyexecdir) diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i index 4d8a64b376..148cad5e63 100644 --- a/cpp/bindings/qpid/python/python.i +++ b/cpp/bindings/qpid/python/python.i @@ -19,7 +19,7 @@ %module cqpid %include "std_string.i" -%include "../../swig_python_typemaps.i" +%include "qpid/swig_python_typemaps.i" /* Needed for get/setPriority methods. Surprising SWIG 1.3.40 doesn't * convert uint8_t by default. */ @@ -159,7 +159,7 @@ QPID_EXCEPTION(UnauthorizedAccess, SessionError) %rename(_setTtl) qpid::messaging::Message::setTtl; -%include "../qpid.i" +%include "qpid/qpid.i" %extend qpid::messaging::Connection { %pythoncode %{ diff --git a/cpp/bindings/qpid/qpid.i b/cpp/bindings/qpid/qpid.i deleted file mode 100644 index 352bafa3c8..0000000000 --- a/cpp/bindings/qpid/qpid.i +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -%{ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Wrapper functions for map-decode and list-decode. This allows us to avoid -// the complexity of output parameter mapping. -// -qpid::types::Variant::Map& decodeMap(const qpid::messaging::Message& msg) { - static qpid::types::Variant::Map map; - map.clear(); - qpid::messaging::decode(msg, map); - return map; -} - -qpid::types::Variant::List& decodeList(const qpid::messaging::Message& msg) { - static qpid::types::Variant::List list; - list.clear(); - qpid::messaging::decode(msg, list); - return list; -} - -%} - -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include - -qpid::types::Variant::Map& decodeMap(const qpid::messaging::Message&); -qpid::types::Variant::List& decodeList(const qpid::messaging::Message&); - - -%{ - -%}; - diff --git a/cpp/bindings/qpid/ruby/CMakeLists.txt b/cpp/bindings/qpid/ruby/CMakeLists.txt index 9b32ff5728..564f5655c8 100644 --- a/cpp/bindings/qpid/ruby/CMakeLists.txt +++ b/cpp/bindings/qpid/ruby/CMakeLists.txt @@ -31,7 +31,9 @@ set(GEM_OUTPUT_FILE ${GEM_OUTPUT_PATH}/pkg/qpid-${qpidc_version}.0.gem) ##------------------------------------------------------ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES CPLUSPLUS ON) -include_directories(${RUBY_INCLUDE_DIRS} ${qpid-cpp_SOURCE_DIR}/include) +include_directories(${RUBY_INCLUDE_DIRS} + ${qpid-cpp_SOURCE_DIR}/include + ${qpid-cpp_SOURCE_DIR}/bindings) swig_add_module(cqpid_ruby ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i) swig_link_libraries(cqpid_ruby qpidmessaging qpidtypes qmf2 ${RUBY_LIBRARY}) @@ -43,7 +45,7 @@ set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_F ##---------------------------------- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid_ruby.so RENAME cqpid.so - DESTINATION ${RUBY_ARCH_DIR} + DESTINATION ${RUBY_PFX_ARCH_DIR} COMPONENT ${QPID_COMPONENT_CLIENT} ) diff --git a/cpp/bindings/qpid/ruby/ChangeLog b/cpp/bindings/qpid/ruby/ChangeLog new file mode 100644 index 0000000000..03813053d2 --- /dev/null +++ b/cpp/bindings/qpid/ruby/ChangeLog @@ -0,0 +1,4 @@ +Verison 0.22: + * Qpid::Messaging::Address can use an address string on creation. + * Qpid::Messaging::Message can use an address string for reply_to. + * Removed errors.rb and the KeyError and SessionNameException errors. diff --git a/cpp/bindings/qpid/ruby/LICENSE b/cpp/bindings/qpid/ruby/LICENSE index 232fd660d6..261eeb9e9f 100644 --- a/cpp/bindings/qpid/ruby/LICENSE +++ b/cpp/bindings/qpid/ruby/LICENSE @@ -1,7 +1,3 @@ -========================================================================= -== Apache License == -========================================================================= - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/cpp/bindings/qpid/ruby/Makefile.am b/cpp/bindings/qpid/ruby/Makefile.am index a2a5dd76bd..398449c7ed 100644 --- a/cpp/bindings/qpid/ruby/Makefile.am +++ b/cpp/bindings/qpid/ruby/Makefile.am @@ -19,7 +19,7 @@ if HAVE_RUBY_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/bindings -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src EXTRA_DIST = CMakeLists.txt ruby.i BUILT_SOURCES = cqpid.cpp @@ -27,7 +27,7 @@ SWIG_FLAGS = -w362,401 rubylibdir = $(RUBY_LIB) -cqpid.cpp: $(srcdir)/ruby.i $(srcdir)/../qpid.i $(srcdir)/../../swig_ruby_typemaps.i +cqpid.cpp: $(srcdir)/ruby.i $(SWIG) -ruby -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqpid.cpp $(srcdir)/ruby.i rubylibarchdir = $(RUBY_LIB_ARCH) diff --git a/cpp/bindings/qpid/ruby/README.rdoc b/cpp/bindings/qpid/ruby/README.rdoc index 5c60a15588..fce87ac3e1 100644 --- a/cpp/bindings/qpid/ruby/README.rdoc +++ b/cpp/bindings/qpid/ruby/README.rdoc @@ -1,45 +1,41 @@ -= Qpid - Open Source AMQP Messaging += Qpid - Ruby language bindings for the Qpid messaging framework. -Qpid is an cross-platform enterprise messaging system. - -Version :: 0.19.0 +Qpid is a cross-platform enterprise messaging system based on the open-source +AMQP protocol. = Links Documents :: http://qpid.apache.org/ -= Installation += Building The Gemfile + +== Prerequisites -You can install Qpid with the following command. +You need to have the Qpid client libraries installed along with the related +development files (headers, etc). To install them, please see: - $ gem install qpid +http://cwiki.apache.org/qpid/developer-pages.html -== Building The Native Code +== Gemfile Creation -The Qpid gem requires that you have available the Qpid libraries and -development header files. To install them, please see: +Simply type: -http://cwiki.apache.org/qpid/developer-pages.html + $ gem build qpid_messaging.gemspec -If you are building the gem within the Qpid development environment -itself, you can specify the location of the Qpid headers and -libraries with: +This will produce a gemfile name qpid_messaging-${VERSION}.gem. -$ ruby extconfig.rb --with-qpid-lib=[path to libqpidclient.so, etc.] -$ make +== Installation -== Examples +You can install Qpid with the following command: -Take a look at the integration tests for examples on how to leverage -the messaging capabilities of Qpid in your Ruby applications. + $ gem install qpid_messaging-${VERSION}.gem == License Licensed to the Apache Software Foundation (ASF) under one or more contributor licensing agreements. -Author:: Darryl L. Pierce (mailto:dpierce@redhat.com) -Copyright:: Copyright (c) 2011, Red Hat, Inc. +Author:: Apache Qpid Project Homepage:: http://qpid.apache.org License:: Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/cpp/bindings/qpid/ruby/Rakefile b/cpp/bindings/qpid/ruby/Rakefile deleted file mode 100644 index 99c3e13c83..0000000000 --- a/cpp/bindings/qpid/ruby/Rakefile +++ /dev/null @@ -1,137 +0,0 @@ -# Rakefile for Qpid -*- ruby -*- -# -# 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. -# - -task :noop - -# look for a root directory for out-of-tree builds - -OUTPUT_DIR=ENV["OUTPUT_DIR"] || "." - -require "rubygems" -require "rubygems/package_task" - -require "rake/clean" -require "rake/extensiontask" -require "rake/rdoctask" -require "rake/testtask" - -require "cucumber/rake/task" -require "spec/rake/spectask" - -CLOBBER.include("pkg") - -load "./lib/qpid/version.rb" - -#------------- -# Gem Details. -#------------- - -NAME = "qpid" -# VERSION = Qpid::VERSION -AUTHOR = "Darryl L. Pierce" -EMAIL = "dpierce@redhat.com" -HOMEPAGE = "http://qpid.apache.org" -SUMMARY = "Qpid is an enterprise messaging framework." - -desc "Default: run all tests." -task :default => :test - -desc "Runs all tests." -task :test => :"test:all" - -#--------------- -# Testing tasks. -#--------------- - -namespace :test do - - desc "Run RSpec tests." - Spec::Rake::SpecTask.new do |t| - t.ruby_opts = ['-rtest/unit'] - t.spec_files = FileList["spec/**/*_spec.rb"] - t.rcov = true - t.rcov_opts = [ - '--exclude', 'lib\/qpid.rb,spec\/,lib\/ruby', - ] - end - - desc "Run all tests (default)." - task :all => [:spec, :features] - - Cucumber::Rake::Task.new(:features) do |t| - t.libs = ["lib", "ext/nonblockio"] - t.cucumber_opts = "--format progress" - end - -end - -#--------------------- -# Documentation tasks. -#--------------------- - -Rake::RDocTask.new(:rdoc => "rdoc", - :clobber_rdoc => "rdoc:clean", - :rerdoc => "rdoc:force") do |rd| - rd.main = "README.rdoc" - rd.options << "--all" - rd.rdoc_files.include("README.rdoc", "lib/**/*.rb") -end - -#----------------- -# Package the gem. -#----------------- - -spec = Gem::Specification.new do |s| - s.name = NAME - s.version = Qpid::VERSION - s.platform = Gem::Platform::RUBY - s.extra_rdoc_files = ["README.rdoc"] - s.summary = SUMMARY - s.description = s.summary - s.author = AUTHOR - s.email = EMAIL - s.homepage = HOMEPAGE - - s.extensions = FileList["ext/**/extconf.rb"] - - s.require_path = "lib" - # DEPRECATED s.autorequire = NAME - s.files = FileList["LICENSE", - "README.rdoc", - "Rakefile", - "TODO", - "lib/**/*.rb", - "test/**/*.rb", - "examples/**/*.rb", - "ext/**/*", - "features/**/*", - "spec/**/*"] -end - -Gem::PackageTask.new(spec) do |pkg| - pkg.package_dir = "#{OUTPUT_DIR}/pkg" -end - -#------------------ -# Build native code -#------------------ - -Rake::ExtensionTask.new("cqpid", spec) - diff --git a/cpp/bindings/qpid/ruby/TODO b/cpp/bindings/qpid/ruby/TODO index 454aac9200..db2aca0195 100644 --- a/cpp/bindings/qpid/ruby/TODO +++ b/cpp/bindings/qpid/ruby/TODO @@ -1,7 +1,12 @@ -TODO Items ------------------------------------------------------------------------------ +Qpid Ruby bindigns TODO List +============================================================================== -Version 0.11.0: - * Deliver the Ruby bindings as a gem. - * Rework the blocking tasks to not bring the main thread to a halt. +Beyond this simple laundry list, you can find the list of bugs and +enhancements to be fixed by going to the Apache Qpid JIRA instance: + http://issues.apache.org/jira/browse/QPID + + +Fixes & Improvements +============================================================================== +* Fix the threading issues with blocking I/O calls (Receiver get/fetch). diff --git a/cpp/bindings/qpid/ruby/examples/client.rb b/cpp/bindings/qpid/ruby/examples/client.rb index 86ec1b7254..f400acfd13 100644 --- a/cpp/bindings/qpid/ruby/examples/client.rb +++ b/cpp/bindings/qpid/ruby/examples/client.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' if __FILE__ == $0 broker = ARGV[1] || "amqp:tcp:localhost:5672" @@ -29,9 +29,7 @@ if __FILE__ == $0 connection.open session = connection.create_session sender = session.create_sender "service_queue" - response_queue = Qpid::Messaging::Address.new("#response-queue", "", - :create => :always, - :delete => :always) + response_queue = Qpid::Messaging::Address.new("#response-queue;{create:always}") receiver = session.create_receiver response_queue ["Twas brillig, and the slithy toves", diff --git a/cpp/bindings/qpid/ruby/examples/drain.rb b/cpp/bindings/qpid/ruby/examples/drain.rb index 9e8f699e8b..8e506ea5cd 100644 --- a/cpp/bindings/qpid/ruby/examples/drain.rb +++ b/cpp/bindings/qpid/ruby/examples/drain.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' require 'optparse' options = { diff --git a/cpp/bindings/qpid/ruby/examples/hello_world.rb b/cpp/bindings/qpid/ruby/examples/hello_world.rb index c014fb8bd5..1f4954dde9 100644 --- a/cpp/bindings/qpid/ruby/examples/hello_world.rb +++ b/cpp/bindings/qpid/ruby/examples/hello_world.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' # This is your classic Hello World application, written in # Ruby, that uses Qpid. It demonstrates how to send and diff --git a/cpp/bindings/qpid/ruby/examples/map_receiver.rb b/cpp/bindings/qpid/ruby/examples/map_receiver.rb index e08bd295ba..16704dd48e 100644 --- a/cpp/bindings/qpid/ruby/examples/map_receiver.rb +++ b/cpp/bindings/qpid/ruby/examples/map_receiver.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672" address = ARGV[1] || "message_queue; {create: always}" diff --git a/cpp/bindings/qpid/ruby/examples/map_sender.rb b/cpp/bindings/qpid/ruby/examples/map_sender.rb index 3fb7ca58e3..1908774c31 100644 --- a/cpp/bindings/qpid/ruby/examples/map_sender.rb +++ b/cpp/bindings/qpid/ruby/examples/map_sender.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672" address = ARGV[1] || "message_queue; {create: always}" diff --git a/cpp/bindings/qpid/ruby/examples/server.rb b/cpp/bindings/qpid/ruby/examples/server.rb index 0cc0e30216..a589bea799 100644 --- a/cpp/bindings/qpid/ruby/examples/server.rb +++ b/cpp/bindings/qpid/ruby/examples/server.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' if __FILE__ == $0 broker = ARGV[0] || "amqp:tcp:localhost:5672" diff --git a/cpp/bindings/qpid/ruby/examples/spout.rb b/cpp/bindings/qpid/ruby/examples/spout.rb index ecc47fb15a..71c04d8709 100644 --- a/cpp/bindings/qpid/ruby/examples/spout.rb +++ b/cpp/bindings/qpid/ruby/examples/spout.rb @@ -19,7 +19,7 @@ $:.unshift File.join(File.dirname(__FILE__), "..", "lib") -require 'qpid' +require 'qpid_messaging' require 'optparse' options = { diff --git a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb b/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb index 90292d4bec..fc9e65d562 100644 --- a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb +++ b/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb @@ -26,9 +26,10 @@ require 'mkmf' # Setup the build environment. -$CFLAGS = "-fPIC -fno-inline -x c++" +$CFLAGS = "-fPIC -fno-inline -x c++ -lstdc++" REQUIRED_LIBRARIES = [ + 'stdc++', 'qpidclient', 'qpidcommon', 'qpidmessaging', diff --git a/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature b/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature index 1f758153af..def686f881 100644 --- a/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature +++ b/cpp/bindings/qpid/ruby/features/creating_a_receiver.feature @@ -25,5 +25,5 @@ Feature: Creating a receiver Scenario: Using an Address object Given an open session - And an Address with the name "create-receiver-test" and subject "foo" and option "create" set to "always" and "delete" set to "always" + And an Address with the string "create-receiver-test;{create:always}" Then creating a receiver with an Address succeeds diff --git a/cpp/bindings/qpid/ruby/features/creating_a_sender.feature b/cpp/bindings/qpid/ruby/features/creating_a_sender.feature index 1c09ff837d..c12b10e054 100644 --- a/cpp/bindings/qpid/ruby/features/creating_a_sender.feature +++ b/cpp/bindings/qpid/ruby/features/creating_a_sender.feature @@ -21,5 +21,5 @@ Feature: Creating a sender Scenario: Using an Address object Given an open session - And an Address with the name "my-queue" and subject "my-subject" and option "create" set to "always" + And an Address with the string "my-queue/my-subject;{create:always}" Then creating a sender with an Address succeeds diff --git a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb index 0531e5ee69..a7eca6f9ce 100644 --- a/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb +++ b/cpp/bindings/qpid/ruby/features/step_definitions/address_steps.rb @@ -17,15 +17,6 @@ # under the License. # -Given /^an Address with the name "([^"]*)" and subject "([^"]*)" and option "([^"]*)" set to "([^"]*)"$/ do |name, subject, key, value| - options = Hash.new - options["#{key}"] = "#{value}" - @address = Qpid::Messaging::Address.new "#{name}", "#{subject}", options -end - -Given /^an Address with the name "([^"]*)" and subject "([^"]*)" and option "([^"]*)" set to "([^"]*)" and "([^"]*)" set to "([^"]*)"$/ do |name, subject, key1, value1, key2, value2| - options = Hash.new - options["#{key1}"] = "#{value1}" - options["#{key2}"] = "#{value2}" - @address = Qpid::Messaging::Address.new "#{name}", "#{subject}", options +Given /^an Address with the string "(.*?)"$/ do |address| + @address = Qpid::Messaging::Address.new "#{address}" end diff --git a/cpp/bindings/qpid/ruby/features/support/env.rb b/cpp/bindings/qpid/ruby/features/support/env.rb index 1d15f56fc9..cc0097ca8b 100644 --- a/cpp/bindings/qpid/ruby/features/support/env.rb +++ b/cpp/bindings/qpid/ruby/features/support/env.rb @@ -19,4 +19,4 @@ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../../lib") -require 'qpid' +require 'qpid_messaging' diff --git a/cpp/bindings/qpid/ruby/lib/qpid.rb b/cpp/bindings/qpid/ruby/lib/qpid.rb deleted file mode 100644 index 1f00c136c1..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid.rb +++ /dev/null @@ -1,29 +0,0 @@ -# -# 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. -# - -require 'qpid/errors' -require 'qpid/duration' -require 'qpid/address' -require 'qpid/encoding' -require 'qpid/message' -require 'qpid/sender' -require 'qpid/receiver' -require 'qpid/session' -require 'qpid/connection' - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/address.rb b/cpp/bindings/qpid/ruby/lib/qpid/address.rb deleted file mode 100644 index 266d8668d6..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/address.rb +++ /dev/null @@ -1,187 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -module Qpid - - module Messaging - - # Address represents an address to which messages can be sent or from - # which they can be received. - # - # An Address can be described using the following pattern: - # - #
[ / ] ; [ { : , ... } ] - # - # where *address* is a simple name and *subject* is a subject or subject - # pattern. - # - # The options, enclosed in curly braces, are key:value pairs delimited by - # a comma. The values can be nested maps also enclosed in curly braces. - # Or they can be lists of values, where they are contained within square - # brackets but still comma delimited, such as: - # - # [value1,value2,value3] - # - # The following are the list of supported options: - # - # [:create] - # Indicates if the address should be created; values are *always*, - # *never*, *sender* or *reciever*. - # - # [:assert] - # Indicates whether or not to assert any specified node properties; - # values are *always*, *never*, *sender* or *receiver*. - # - # [:delete] - # Indicates whether or not to delete the addressed node when a sender - # or receiver is cancelled; values are *always*, *never*, *sender* or - # *receiver*. - # - # [:node] - # A nested map describing properties for the addressed node. Properties - # are *type* (*topic* or *queue*), *durable* (a boolean), *x-declare* - # (a nested map of amqp 0.10-specific options) and *x-bindings*. (nested - # list which specifies a queue, exchange or a binding key and arguments. - # - # [:link] - # A nested map through which properties of the link can be specified; - # properties are *durable*, *reliability*, *x-declare*, *x-subscribe* - # and *x-bindings*. - # - # [:mode] - # (*For receivers only*) indicates whether the receiver should consume - # or browse messages; values are *consume* (the default) and *browse*. - # - class Address - - # Creates a new +Address+ object. - # - # ==== Options - # - # * name - The name for the +Address+. - # * subject - The subject for the +Address+ - # * :create - See the class documentation. - # * :assert - See the class documentation. - # * :delete - See the class documentation. - # * :node - See the class documentation. - # * :link - See the class documentation. - # * :mode - See the class documentation. - # - # ==== Examples - # - # addr = Qpid::Messaging::Address.new "my-queue" - # addr = Qpid::Messaging::Address.new "my-queue", "testing", :create => :always - # - def initialize(name, subject, options = {}, _type = "", address_impl = nil) - @address_impl = address_impl || Cqpid::Address.new(name, subject, convert_options(options), _type) - end - - def address_impl # :nodoc: - @address_impl - end - - # Returns the name for the +Address+. - # - # ==== Examples - # - # puts "The address name is #{addr.name}." - # - def name; @address_impl.getName; end - - # Sets the name for the +Address+. - # - # ==== Examples - # - # addr.name = "my-new-queue" - # - def name=(name); @address_impl.setName name; end - - # Returns the subject for the +Address+. - # - # ==== Examples - # - # puts "The subject is #{addr.subject}." - # - def subject; @address_impl.getSubject; end - - # Sets the subject for the +Address+. - # - # ==== Examples - # - # addr.subject = "testing" - # - def subject=(subject); @address_impl.setSubject(subject); end - - # Returns the type for the +Address+. - # - # ==== Examples - # - # puts "The address is a #{address.address_type}." - # - #--- - # We cannot use "type" since that clashes with the Ruby object.type - # identifier. - def address_type; @address_impl.getType; end - - # Sets the type for the +Address+. - # - # The type of the address determines how +Sender+ and +Receiver+ objects - # are constructed for it. If no type is specified then it will be - # determined by querying the broker. - # - # ===== Options - # - # * type - the address type - # - def address_type=(type); @address_impl.setType(type); end - - # Returns the options. - def options; @address_impl.getOptions; end - - # Sets the options for the address. - # - # *NOTE:* See the class documentation for more details on options. - # - # ==== Examples - # - # addr.options = :create => :always - # - def options=(options = {}); @address_impl.setOptions(convert_options(options)); end - - def to_s # :nodoc: - @address_impl.str - end - - private - - def convert_options(options) - result = {} - options.each_pair {|key, value| result[key.to_s] = value.to_s} - - return result - end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/connection.rb b/cpp/bindings/qpid/ruby/lib/qpid/connection.rb deleted file mode 100644 index 12669bc947..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/connection.rb +++ /dev/null @@ -1,162 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -module Qpid - - module Messaging - - # Establishes a connection to a remote endpoint. - class Connection - - attr_reader :options # :nodoc: - - # Creates a connection object, but does not actually connect to - # the specified location. - # - # ==== Options - # - # :url - the URL for the broker (def. +"localhost"+) - # :options - connection options (def. +{}+) - # - # ==== Controlling Reconnect Behavior - # - # The following connection options can be used to configure - # the reconnection behavior for this connection. - # - # * :username - # * :password - # * :heartbeat - # * :tcp_nodelay - # * :sasl_mechanism - # * :sasl_service - # * :sasl_min_ssf - # * :sasl_max_ssf - # * :transport - # * :reconnect - +true+ or +false+; indicates wehtehr to attempt reconnections - # * :reconnect_timeout - the number of seconds to attempt reconnecting - # * :reconnect_limit - the number of retries before reporting failure - # * :reconnect_interval_min - initial delay, in seconds, before attempting a reconnection - # * :reconnect_interval_max - number of seconds to wait before additional reconnect attempts - # * :reconnect_interval - shorthand for setting both min and max values - # * :reconnect_urls - a list of alternate URLs to use for reconnection attempts - # - # ==== Examples - # - # conn = Qpid::Messaging::Connnection.new - # conn = Qpid::Messaging::Connection.new :url => "amqp:tcp:broker1.domain.com:5672" - # conn = Qpid::Messaging::Connection.new :options => {:username => "login", :password => "password"} - # - def initialize(opts = {}) - @url = opts[:url] || "localhost" - @options = convert_options(opts[:options] || {}) - @connection_impl = opts[:impl] || Cqpid::Connection.new(@url, @options) - end - - def connection_impl # :nodoc: - @connection_impl - end - - # Establishes the connection. - # - # ==== Examples - # - # conn.open unless conn.open? - # - def open - @connection_impl.open - end - - # Reports whether the connection is open. - # - # ==== Examples - # - # conn.close if conn.open? - # - def open?; true && !@connection_impl.nil? && @connection_impl.isOpen; end - - # Closes the connection. - def close; @connection_impl.close; end - - # Creates a new session. - # - # ==== Arguments - # - # * :name - specifies the name for this session - # * :transactional - if +true+ then a creates a transaction session (def. +false+) - # - # ==== Examples - # - # session = conn.create_session :name => "session1" - # session = conn.create_session :transaction => true - # - def create_session(args = {}) - name = args[:name] || "" - if open? - if args[:transactional] - session = @connection_impl.createTransactionalSession name - else - session = @connection_impl.createSession name - end - return Session.new(self, session) - else - raise RuntimeError.new "No connection available." - end - end - - # Returns a session for the specified session name. - # - # ==== Examples - # - # begin - # session = conn.session "mysession" - # rescue SessionNameException => error - # puts "No such session." - # end - # - def session name - begin - session_impl = @connection_impl.getSession name - Qpid::Messaging::Session.new self, session_impl if session_impl - rescue - raise Qpid::Messaging::SessionNameException.new "No such session: #{name}" - end - end - - # Returns the username used to authenticate with the connection. - def authenticated_username; @connection_impl.getAuthenticatedUsername if open?; end - - private - - def convert_options(options) - result = {} - unless options.nil? || options.empty? - options.each_pair {|key, value| result[key.to_s] = value.to_s} - end - - return result - end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/duration.rb b/cpp/bindings/qpid/ruby/lib/qpid/duration.rb deleted file mode 100644 index e1ddd79cb6..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/duration.rb +++ /dev/null @@ -1,95 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -module Qpid - - module Messaging - - # A Duration represents a period of time in milliseconds - # - # It defines the following named values as symbols: - # - # [:FOREVER] - # The maximum integer value for the platform. Effectively this will wait - # forever. - # - # [:IMMEDIATE] - # An alias for 0 milliseconds. - # - # [:SECOND] - # An alias for 1,000 milliseconds. - # - # [:MINUTE] - # And alias for 60,000 millisecons. - # - class Duration - - # Creates a Duration with the specified length, in milliseconds. - # - # ==== Options - # - # * length - The duration in milliseconds. - # - # ==== Examples - # - # # Wait up to 10 seconds for an incoming message - # receiver.get Qpid::Messaging::Duration.new 10000 - # - def initialize length - @duration_impl = Cqpid::Duration.new length - end - - def duration_impl # :nodoc: - @duration_impl - end - - # Returns the period of time in milliseconds - # - # ==== Examples - # - # duration = Qpid::Messaging::Duration.new :length => 5000 - # puts "Waiting #{duration.milliseconds} ms for a message." - # msg = receiver.fetch duration - # - def milliseconds - @duration_impl.getMilliseconds - end - - def self.add_item(key, value) # :nodoc: - @hash ||= {} - @hash[key] = Duration.new value - end - - def self.const_missing(key) # :nodoc: - @hash[key] - end - - self.add_item :FOREVER, Cqpid::Duration.FOREVER.getMilliseconds - self.add_item :IMMEDIATE, Cqpid::Duration.IMMEDIATE.getMilliseconds - self.add_item :SECOND, Cqpid::Duration.SECOND.getMilliseconds - self.add_item :MINUTE, Cqpid::Duration.MINUTE.getMilliseconds - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb b/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb deleted file mode 100644 index 2f20fab18e..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb +++ /dev/null @@ -1,60 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -module Qpid - - module Messaging - - # Encodes the supplied content into the given message. - def self.encode content, message, encoding = nil - prepared = content - case content - when Hash - prepared = {} - content.each_pair do |key,value| - prepared[key.to_s] = value.to_s - end - Cqpid::encode prepared, message.message_impl - when Array - prepared = [] - content.each {|value| prepared << value.to_s} - Cqpid::encode prepared, message.message_impl - end - end - - # Decodes and returns the message's content. - def self.decode(message, content_type = nil) - content_type = message.content_type unless content_type - - case content_type - when "amqp/map" - Cqpid.decodeMap message.message_impl - when "amqp/list" - Cqpid.decodeList message.message_impl - end - - message.content - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/errors.rb b/cpp/bindings/qpid/ruby/lib/qpid/errors.rb deleted file mode 100644 index c98eb1ac12..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/errors.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -# 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 Qpid - - module Messaging - - class KeyError < RuntimeError; end - - class SessionNameException < Exception - def initialize(msg); super(msg); end - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/message.rb b/cpp/bindings/qpid/ruby/lib/qpid/message.rb deleted file mode 100644 index edef0ac2a0..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/message.rb +++ /dev/null @@ -1,368 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -module Qpid - - module Messaging - - # A +Message+ represents an routable piece of information. - # - # The content for a message is automatically encoded and decoded. - # - class Message - - # Creates a new instance of +Message+. - # - # ==== Options - # - # * :content - The content. - # - # ==== Examples - # - # message = Qpid::Messaging::Message.new :content => "This is a message." - # - def initialize(args = {}) - @message_impl = (args[:impl] if args[:impl]) || nil - @message_impl = Cqpid::Message.new if @message_impl.nil? - @content = nil - args = {} if args.nil? - self.content = args[:content] if args[:content] - end - - def message_impl # :nodoc: - @message_impl - end - - # Sets the address to which replies should be sent for the +Message+. - # - # *NOTE:* The address must be an instance of Address. - # - # ==== Options - # - # * address - an instance of +Address+ - # - # ==== Examples - # - # msg.reply_to = Qpid:Messaging::Address.new "my-responses" - # - def reply_to=(address) - raise ArgumentError, "Agument must be an Address" unless address.is_a? Qpid::Messaging::Address - @message_impl.setReplyTo address.address_impl - end - - # Returns the reply to address for the +Message+. - # - def reply_to - address_impl = @message_impl.getReplyTo - # only return an address if a reply to was specified - Qpid::Messaging::Address.new(nil, nil, nil, nil, address_impl) if address_impl - end - - # Sets the subject for the +Message+. - # - # ==== Options - # - # * subject - the subject - # - # ==== Examples - # - # msg.subject = "mysubject" - # - def subject=(subject); @message_impl.setSubject subject; end - - # Returns the subject of the +Message+. - # - # ==== Options - # - # puts "The subject is #{msg.subject}" - # - def subject; @message_impl.getSubject; end - - # Sets the content type for the +Message+. - # - # This should be set by the sending applicaton and indicates to - # recipients of the message how to interpret or decode the content. - # - # By default, only dictionaries and maps are automatically given a content - # type. If this content type is replaced then retrieving the content will - # not behave correctly. - # - # ==== Options - # - # * content_type - the content type. - # - def content_type=(content_type); @message_impl.setContentType content_type; end - - # Returns the content type for the +Message+. - # - # ==== Examples - # - # case msg.content_type - # when "myapp/image" - # ctl.handle_image msg - # end - # when "myapp/audio" - # ctl.handle_audio msg - # end - # end - # - def content_type; @message_impl.getContentType; end - - # Sets the message id. - # - # *NOTE:* this field must be a UUID type currently. A non-UUID value will - # be converted to a zero UUID, though a blank ID will be left untouched. - # - # ==== Options - # - # * id - the id - # - # ==== Examples - # - # - def message_id=(message_id); @message_impl.setMessageId message_id.to_s; end - - # Returns the message id. - # - # See +message_id=+ for details. - def message_id; @message_impl.getMessageId; end - - # Sets the user id for the +Message+. - # - # This should in general be the user-id which was used when authenticating - # the connection itself, as the messaging infrastructure will verify - # this. - # - # See +Qpid::Messaging::Connection.authenticated_username+ - # - # *NOTE:* If the id is not a +String+ then the id is set using - # the object's string representation. - # - # ==== Options - # - # * id - the id - # - def user_id=(user_id); @message_impl.setUserId user_id; end - - # Returns the user id for the +Message+. - # - # See +user_id=+ for details. - # - def user_id; @message_impl.getUserId; end - - # Sets the correlation id of the +Message+. - # - # The correlation id can be used as part of a protocol for message - # exchange patterns; e.g., a requestion-response pattern might require - # the correlation id of the request and the response to match, or it - # might use the message id of the request as the correlation id on - # the response - # - # *NOTE:* If the id is not a +String+ then the id is setup using - # the object's string representation. - # - # ==== Options - # - # * id - the id - # - def correlation_id=(correlation_id); @message_impl.setCorrelationId correlation_id; end - - # Returns the correlation id of the +Message+. - # - # *NOTE:* See +correlation_id=+ for details. - # - def correlation_id; @message_impl.getCorrelationId; end - - # Sets the priority of the +Message+. - # - # This may be used by the messaging infrastructure to prioritize - # delivery of messages with higher priority. - # - # *NOTE:* If the priority is not an integer type then it is set using - # the object's integer representation. If the integer value is greater - # than 8-bits then only the first 8-bits are used. - # - # ==== Options - # - # * priority - the priority - # - def priority=(priority); @message_impl.setPriority priority; end - - # Returns the priority for the +Message+. - # - def priority; @message_impl.getPriority; end - - # Sets the time-to-live in milliseconds. - # - # ==== Options - # - # * duration - the number of milliseconds - # - def ttl=(duration) - if duration.is_a? Qpid::Messaging::Duration - @message_impl.setTtl duration.duration_impl - else - @message_impl.setTtl Cqpid::Duration.new duration.to_i - end - end - - # Returns the time-to-live in milliseconds. - def ttl; Qpid::Messaging::Duration.new @message_impl.getTtl.getMilliseconds; end - - # Sets the durability of the +Message+. - # - # This is a hint to the messaging infrastructure that the message - # should be persisted or otherwise stored. This helps to ensure - # that th emessage is not lost during to failures or a shutdown. - # - # ==== Options - # - # * durable - the durability flag (def. false) - # - def durable=(durable); @message_impl.setDurable durable; end - - # Returns the durability for the +Message+. - # - def durable; @message_impl.getDurable; end - - # This is a hint to the messaging infrastructure that if de-duplication - # is required, that this message should be examined to determine if it - # is a duplicate. - # - # ==== Options - # - # * redelivered - sets the redelivered state (def. false) - # - # ==== Examples - # - # # processed is an array of processed message ids - # msg.redelivered = true if processed.include? msg.message_id - # - def redelivered=(redelivered); @message_impl.setRedelivered redelivered; end - - # Returns whether the +Message+ has been marked as redelivered. - # - def redelivered; @message_impl.getRedelivered; end - - # Returns all named properties. - # - # *NOTE:* It is recommended to use the []= method for - # retrieving and setting properties. Using this method may - # result in non-deterministic behavior. - # - def properties; @message_impl.getProperties; end - - # Returns the value for the named property. - # - # ==== Options - # - # * name - the property name - # - # ==== Examples - # - # # use of message properties to mark a message as digitally signed - # verify(msg) if msg[:signed] - # - def [](key); self.properties[key.to_s]; end - - # Assigns a value to the named property. - # - # *NOTE:* Both the key or the value may be a symbol, but they will - # both be converted to a +String+ for ease of transport. - # - # ==== Options - # - # * name - the property name - # * value - the property value - def []=(key, value); @message_impl.setProperty(key.to_s, value.to_s); end - - # Sets the content for the +Message+. - # - # Content is automatically encoded for Array and Hash types. Other types - # need to set their own content types (via +content_type+) in order to - # specify how recipients should process the content. - # - # ==== Options - # - # * content - the content - # - # ==== Examples - # - # msg.content = "This is a simple message." # a simple message - # msg.content = {:foo => :bar} # content is automatically encoded - # - def content=(content) - content_type = nil - @content = content - case @content - when Hash - content_type = "amqp/map" - new_content = {} - content.each_pair{|key, value| new_content[key.to_s] = value.to_s} - @content = new_content - when Array - new_content = [] - content_type = "amqp/list" - content.each {|element| new_content << element.to_s} - @content = new_content - end - if content_type.nil? - @message_impl.setContent @content - else - Qpid::Messaging.encode @content, self, content_type - end - end - - # Returns the content of the +Message+. - # - # Content is automatically decoded based on the specified content type. - # If the content type is application-specific, then no decoding is - # performed and the content is returnedas a +String+ representation. - # - # For example, if an array of integers are sent, then the receiver will - # find the message content to be an array of String objects, where each - # String is a representation of the sent integer value. - # - def content - if @content.nil? - @content = @message_impl.getContent - - # decode the content is necessary if it - # has an encoded content type - if ["amqp/list", "amqp/map"].include? @message_impl.getContentType - @content = Qpid::Messaging.decode(self, - @message_impl.getContentType) - end - - end - @content - end - - # Returns the content's size. - # - def content_size; @message_impl.getContentSize; end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb b/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb deleted file mode 100644 index 0ce16309ed..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb +++ /dev/null @@ -1,186 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -require 'qpid/duration' - -module Qpid - - module Messaging - - # Receiver is the entity through which messages are received. - # - # An instance of Receiver can only be created using an active (not - # previously closed) Session. - # - # ==== Example - # - # conn = Qpid::Messaging::Connection.new :url => "mybroker:5762" - # conn.open - # session = conn.create_session - # receiver = session.create_receiver "my-sender-queue" - class Receiver - - def initialize(session, receiver_impl) # :nodoc: - @session = session - @receiver_impl = receiver_impl - end - - def receiver_impl # :nodoc: - @receiver_impl - end - - # Retrieves a message from the local queue, or waits for up to - # the duration specified for one to become available. - # - # If a block is given, then it will be invaked after the next message - # is received or the call times out, passing in the message or nil - # respectively. - # - # ==== Options - # * duration - the timeout to wait (def. Duration::FOREVER) - # - # ==== Examples - # - # msg = rcvr.get # Uses the default timeout of forever - # - # msg = rcvr.get Qpid::Messaging::Duration::IMMEDIATE # returns a message or exits immediately - # - # # passes in a block to handle the received message - # rcvr.get Qpid::Messaging::Duration::SECOND do |message| - # if message.nil? - # puts "No message was received." - # else - # puts "Received this message: #{message.content}" - # end - # end - def get(duration = Qpid::Messaging::Duration::FOREVER) - message_impl = @receiver_impl.get duration.duration_impl - create_message_wrapper message_impl unless message_impl.nil? - end - - # Retrieves a message from the receiver's subscription, or waits - # for up to the duration specified for one to become available. - # - # If a block is given, then it will be invaked after the next message - # is received or the call times out, passing in the message or nil - # respectively. - # - # ==== Options - # * duration - the timeout to wait (def. Duration::FOREVER) - # - # ==== Examples - # - # msg = rcvr.fetch # Uses the default timeout of forever - # - # msg = rcvr.fetch Qpid::Messaging::Duration::IMMEDIATE # returns a message or exits immediately - # - # # passes in a block to handle the received message - # rcvr.fetch Qpid::Messaging::Duration::SECOND do |message| - # if message.nil? - # puts "No message was received." - # else - # puts "Received this message: #{message.content}" - # end - # end - def fetch(duration = Qpid::Messaging::Duration::FOREVER) - message_impl = @receiver_impl.fetch duration.duration_impl - create_message_wrapper message_impl unless message_impl.nil? - end - - # Sets the capacity for this +Receiver+. - # - # ==== Options - # - # * capacity - the capacity - # - # ==== Examples - # - # receiver.capacity = 50 # sets the incoming capacity to 50 messages - # - def capacity=(capacity); @receiver_impl.setCapacity capacity; end - - # Returns the capacity. - # - # - # The capacity is the numnber of incoming messages that can be held - # locally before being fetched. - # - # ==== Examples - # - # puts "The receiver can hold #{rcv.capacity} messages." - # - def capacity; @receiver_impl.getCapacity; end - - # Returns the number of slots for receiving messages. - # - # This differs from +capacity+ in that it is the available slots in - # the capacity for holding incoming messages, where available <= capacity. - # - # ==== Examples - # - # puts "You can receive #{rcv.available} messages before blocking." - # - def available; @receiver_impl.getAvailable; end - - # Returns the number of messages that have been received and acknowledged - # but whose acknowledgements have not been confirmed by the sender. - # - # ==== Examples - # - # puts "You have #{rcv.unsettled} messages to be confirmed." - # - def unsettled; @receiver_impl.getUnsettled; end - - # Closes this +Receiver+. - # - # This does not affect the +Session+. - def close; @receiver_impl.close; end - - # Returns whether the receiver is closed. - # - # ==== Examples - # - # recv.close unless recv.closed? - # - def closed?; @receiver_impl.isClosed; end - - # Returns the name of this +Receiver+. - # - # ==== Examples - # - # puts "Receiver: #{recv.name}" - def name; @receiver_impl.getName; end - - # Returns the Session for this +Receiver+. - def session; @session; end - - private - - def create_message_wrapper message_impl # :nodoc: - Qpid::Messaging::Message.new(:impl => message_impl) - end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/sender.rb b/cpp/bindings/qpid/ruby/lib/qpid/sender.rb deleted file mode 100644 index 97227622f5..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/sender.rb +++ /dev/null @@ -1,152 +0,0 @@ -# -# 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 Qpid - - module Messaging - - # Sender is the entity through which messages sent. - # - # An instance of Sender can only be created using an active (not previously - # closed) Session. - # - # ==== Examples - # - # conn = Qpid::Messaging::Connection.new :url => "mybroker:5762" - # conn.open - # session = conn.create_session - # sender = session.create_session "my-sender-queue;{create:always}" - class Sender - - def initialize(session, sender_impl) # :nodoc: - @session = session - @sender_impl = sender_impl - end - - def sender_impl # :nodoc: - @sender_impl - end - - # Sends a message. - # - # If a block is given, then it will be invoked after the message - # is sent. - # - # ==== Options - # - # * message - The message to send. - # * :sync - See note below on synching. - # - # ==== Synching - # - # If :sync => true, then the call will block until the broker confirms - # receipt of the message. Otherwise it will only block for available - # capacity; i.e., until pending is equal to capacity. - # - # ==== Examples - # - # sender.send message do |message| - # puts "Message sent: #{message.content}" - # end - # - def send(message, args = {}, &block) - sync = args[:sync] || false - @sender_impl.send message.message_impl, sync - block.call message unless block.nil? - end - - # Closes this +Sender+. - # - # This does not affect the +Session+. - def close; @sender_impl.close; end - - # Returns the human-readable name for this +Sender+. - # - # ==== Examples - # - # puts "Sender: #{sender.name}" - # - def name; @sender_impl.getName; end - - # Sets the capacity for this +Sender+. - # - # The capacity is the number of outgoing messages that can be held - # pending confirmation or receipt by the broker. - # - # ==== Options - # - # * capacity - the capacity - # - # ==== Examples - # - # sender.capacity = 50 # sets the outgoing capacity to 50 messages - # - def capacity=(capacity); @sender_impl.setCapacity capacity; end - - # Returns the capacity. - # - # The capacity is the total number of outgoing messages that can be - # sent before a called to +send+ begins to block by default. - # - # ==== Examples - # - # puts "You can send a maximum of #{sender.capacity} messages." - # - def capacity; @sender_impl.getCapacity; end - - # Returns the number of messages sent that are pending receipt - # confirmation by the broker. - # - # ==== Examples - # - # if sender.unsettled > 0 - # puts "There are #{sender.unsettled} messages pending." - # end - # - def unsettled; @sender_impl.getUnsettled; end - - # Returns the available slots for sending messages. - # - # This differs from +capacity+ in that it is the available slots in - # the senders capacity for holding outgoing messages. The difference - # between capacity and available is the number of messages that - # have not been delivered yet. - # - # ==== Examples - # - # puts "You can send #{sender.available} messages before blocking." - # - def available - @sender_impl.getAvailable - end - - # Returns the +Session+ for this sender. - # - # ==== Examples - # - # recv.session.close if done - # - def session; @session; end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/session.rb b/cpp/bindings/qpid/ruby/lib/qpid/session.rb deleted file mode 100644 index feb8aa5bb4..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/session.rb +++ /dev/null @@ -1,271 +0,0 @@ -# -# 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. -# - -require 'cqpid' - -require 'qpid/errors' - -module Qpid - - module Messaging - - # A Session represents a distinct conversation between end points. - class Session - - def initialize(connection, session) # :nodoc: - @connection = connection - @session_impl = session - @senders = Hash.new - @receivers = Hash.new - end - - def session_impl # :nodoc: - @session_impl - end - - # Returns the +Connection+ associated with this session. - def connection - @connection - end - - # Creates a new endpoint for sending messages. - # - # The +address+ can either be an instance +Address+ or else a - # string that describes an address endpoint. - # - # ==== Arguments - # - # * +address+ The end point address. - # - # ==== Examples - # - # sender = session.create_sender "my-queue;{create:always}" - # - def create_sender(address) - _address = address - - if address.class == Qpid::Messaging::Address - _address = address.address_impl - end - - sender_impl = @session_impl.createSender(_address) - sender_name = sender_impl.getName - - @senders[sender_name] = Qpid::Messaging::Sender.new(self, sender_impl) - - @senders[sender_name] - end - - # Retrieves the +Sender+ with the specified name. - # - # The +Sender+ must have been previously created using - # the +create_sender+ method. - # - # ==== Arguments - # - # * +name+ The +Sender+ name. - # - # ==== Examples - # - # sender = session.sender "my-queue" - # - def sender(name) - raise Qpid::Messaging::KeyError, "No such sender: #{name}" unless @senders.has_key? name - - @senders[name] - end - - # Creates a new endpoint for receiving messages. - # - # The +address+ can either be an instance +Address+ or else a - # string that describes an address endpoint. - # - # ==== Arguments - # - # * +address+ The end point address. - # - # ==== Examples - # - # receiver = session.create_receiver "my-queue" - # - def create_receiver(address) - result = nil - receiver_impl = nil - - if address.class == Qpid::Messaging::Address - address_impl = address.address_impl - receiver_impl = @session_impl.createReceiver address_impl - else - receiver_impl = @session_impl.createReceiver(address) - end - - receiver_name = receiver_impl.getName - - @receivers[receiver_name] = Qpid::Messaging::Receiver.new self, receiver_impl - - @receivers[receiver_name] - end - - # Retrieves the +Receiver+ with the specified name. - # - # The +Receiver+ must have been previously created using - # the +create_receiver+ method. - # - # ==== Arguments - # - # * +name+ The +Receiver+ name. - # - # ==== Examples - # - # receiver = session.receiver "my-queue" - # - def receiver(name) - raise Qpid::Messaging::KeyError, "No such receiver: #{name}" unless @receivers.has_key? name - - @receivers[name] - end - - # Closes the +Session+ and all associated +Sender+ and +Receiver+ instances. - # - # NOTE: All +Session+ instances for a +Connection+ are closed when the - # +Connection+ is closed. - def close; @session_impl.close; end - - # Commits any pending transactions for a transactional session. - def commit; @session_impl.commit; end - - # Rolls back any uncommitted transactions on a transactional session. - def rollback; @session_impl.rollback; end - - # Acknowledges one or more outstanding messages that have been received - # on this session. - # - # ==== Arguments - # - # * :message - if specified, then only the +Message+ specified is acknowledged - # * :sync - if true then the call will block until processed by the server (def. false) - # - # ==== Examples - # - # session.acknowledge # acknowledges all received messages - # session.acknowledge :message => message # acknowledge one message - # session.acknowledge :sync => true # blocks until the call completes - # - #-- - # TODO: Add an optional block to be used for blocking calls. - #++ - def acknowledge(args = {}) - sync = args[:sync] || false - message = args[:message] if args[:message] - - unless message.nil? - @session_impl.acknowledge message.message_impl, sync - else - @session_impl.acknowledge sync - end - end - - # Rejects the specified message. A rejected message will not be - # redelivered. - # - # NOTE: A message cannot be rejected once it has been acknowledged. - def reject(message); @session_impl.reject message.message_impl; end - - # Releases the message, which allows the broker to attempt to - # redeliver it. - # - # NOTE: A message connot be released once it has been acknowled. - def release(message); @session_impl.release message.message_impl; end - - # Requests synchronization with the server. - # - # ==== Arguments - # - # * :block - if true then the call blocks until the server acknowledges it (def. false) - # - #-- - # TODO: Add an optional block to be used for blocking calls. - #++ - def sync(args = {}) - block = args[:block] || false - @session_impl.sync block - end - - # Returns the total number of receivable messages, and messages already - # received, by +Receiver+ instances associated with this +Session+. - def receivable; @session_impl.getReceivable; end - - # Returns the number of messages that have been acknowledged by this session - # whose acknowledgements have not been confirmed as processed by the server. - def unsettled_acks; @session_impl.getUnsettledAcks; end - - # Fetches the +Receiver+ for the next message. - # - # ==== Arguments - # - # * timeout - time to wait for a +Receiver+ before timing out - # - # ==== Examples - # - # recv = session.next_receiver # wait forever for the next +Receiver+ - # # execute a block on the next receiver - # session.next_receiver do |recv| - # msg = recv.get - # puts "Received message: #{msg.content}" - # end - def next_receiver(timeout = Qpid::Messaging::Duration::FOREVER, &block) - receiver_impl = @session_impl.nextReceiver(timeout.duration_impl) - - unless receiver_impl.nil? - recv = Qpid::Messaging::Receiver.new self, receiver_impl - block.call recv unless block.nil? - end - - return recv - end - - # Returns true if there were exceptions on this session. - # - # ==== Examples - # - # puts "There were session errors." if @session.errors? - def errors?; @session_impl.hasError; end - - # If the +Session+ has been rendered invalid due to some exception, - # this method will result in that exception being raised. - # - # If none have occurred, then no exceptions are raised. - # - # ==== Examples - # - # if @session.errors? - # begin - # @session.errors - # rescue Exception => error - # puts "An error occurred: #{error}" - # end - # end - def errors; @session_impl.checkError; end - - end - - end - -end - diff --git a/cpp/bindings/qpid/ruby/lib/qpid/version.rb b/cpp/bindings/qpid/ruby/lib/qpid/version.rb deleted file mode 100644 index 39524e428f..0000000000 --- a/cpp/bindings/qpid/ruby/lib/qpid/version.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# 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 Qpid - - module Version - - NUMBERS = [MAJOR = 0, - MINOR = 17, - BUILD = 0] - end - - VERSION = Version::NUMBERS.join('.') - -end diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging.rb new file mode 100644 index 0000000000..2b5348f298 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging.rb @@ -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. +#++ + +require 'cqpid' +require 'qpid_messaging/duration' +require 'qpid_messaging/address' +require 'qpid_messaging/encoding' +require 'qpid_messaging/message' +require 'qpid_messaging/sender' +require 'qpid_messaging/receiver' +require 'qpid_messaging/session' +require 'qpid_messaging/connection' + +module Qpid + + # The Qpid Messaging framework is an enterprise messaging framework + # based on the open-source AMQP protocol. + # + # ==== Example Application + # + # Here is a simple example application. It creates a link to a broker located + # on a system named *broker.myqpiddomain.com*. It then creates a new messaging + # queue named "qpid-examples" and publishes a message to it. It then consumes + # that same message and closes the connection. + # + # require 'rubygems' + # gem 'qpid_messaging' + # require 'qpid_messaging' + # + # # create a connection, open it and then create a session named "session1" + # conn = Qpid::Messaging::Connection.new :name => "broker.myqpiddomain.com" + # conn.open + # session = conn.create_session "session1" + # + # # create a sender and a receiver + # # the sender marks the queue as one that is deleted when trhe sender disconnects + # send = session.create_sender "qpid-examples;{create:always,delete:always}" + # recv = session.create_receiver "qpid-examples" + # + # # create an outgoing message and send it + # outgoing = Qpid::Messaging::Message.new :content => "The time is #{Time.new}" + # sender.send outgoing + # + # # set the receiver's capacity to 10 and then check out many messages are pending + # recv.capacity = 10 + # puts "There are #{recv.available} messages waiting." # should report 1 message + # + # # get the nextwaiting message, which should be in the local queue now, + # # and output the contents + # incoming = recv.get Qpid::Messaging::Duration::IMMEDIATE + # puts "Received the following message: #{incoming.content}" + # # the output should be the text that was sent earlier + # + # # acknowledge the message, letting the sender know the message was received + # puts "The sender currently has #{send.unsettled} message(s) pending." + # # should report 1 unsettled message + # session.acknowledge incoming # acknowledge the received message + # puts "Now sender currently has #{send.unsettled} message(s) pending." + # # should report 0 unsettled messages + # + # # close the connection + # conn.close + # + module Messaging; end + +end diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/address.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/address.rb new file mode 100644 index 0000000000..0879f0fcd1 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/address.rb @@ -0,0 +1,200 @@ +#-- +# 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 Qpid + + module Messaging + + # Address represents an address to which messages can be sent or from + # which they can be received. + # + # == The +Address+ String + # + # An +Address+ can be described using the following pattern: + # + #
[ / ] ; [ { : , ... } ] + # + # where *address* is a simple name and *subject* is a subject or subject + # pattern. + # + # === Options + # + # The options, enclosed in curly braces, are key:value pairs delimited by + # a comma. The values can be nested maps also enclosed in curly braces. + # Or they can be lists of values, where they are contained within square + # brackets but still comma delimited, such as: + # + # [value1,value2,value3] + # + # The following are the list of supported options: + # + # [create] + # Indicates if the address should be created; values are *always*, + # *never*, *sender* or *reciever*. + # + # [assert] + # Indicates whether or not to assert any specified node properties; + # values are *always*, *never*, *sender* or *receiver*. + # + # [delete] + # Indicates whether or not to delete the addressed node when a sender + # or receiver is cancelled; values are *always*, *never*, *sender* or + # *receiver*. + # + # [node] + # A nested map describing properties for the addressed node. Properties + # are *type* (*topic* or *queue*), *durable* (a boolean), *x-declare* + # (a nested map of amqp 0.10-specific options) and *x-bindings* (nested + # list which specifies a queue, exchange or a binding key and arguments). + # + # [link] + # A nested map through which properties of the link can be specified; + # properties are *durable*, *reliability*, *x-declare*, *x-subscribe* + # and *x-bindings*. + # + # [mode] + # (*For receivers only*) indicates whether the receiver should consume + # or browse messages; values are *consume* (the default) and *browse*. + class Address + + # Creates a new +Address+ from an address string. + # + # ==== Attributes + # + # * +address+ - the address string + # + # ==== Examples + # + # # create a new address for a queue named "my-queue" that will + # # be created if it doesn't already exist + # addr = Qpid::Messaging::Address.new "my-queue;{create:always}" + # + def initialize(address, address_impl = nil) + @address_impl = address_impl || Cqpid::Address.new(address) + end + + def address_impl # :nodoc: + @address_impl + end + + # Returns the name for the +Address+. + # + # ==== Examples + # + # # display the name of the address + # addr = Qpid::Messaging::Address.new "foo;{create:always}" + # # outputs the word 'foo' + # puts addr.name + # + def name; @address_impl.getName; end + + # Sets the name for the +Address+. + # + # ==== Examples + # + # # create a new address with the name "my-queue" + # addr = Qpid::Messaging::Address.new "my-queue/my-subject;{create:always}" + # # changes the name to "my-new-queue" + # addr.name = "my-new-queue" + # + def name=(name); @address_impl.setName name; end + + # Returns the subject for the +Address+. + # + # ==== Examples + # + # # creates a new address with the subject "bar" + # addr = Qpid::Messaging::Address.new "my-queue/bar;{create:always}" + # + def subject; @address_impl.getSubject; end + + # Sets the subject for the +Address+. + # + # ==== Examples + # + # # creates an address with the subject "example" + # addr = Qpid::Messaging::Address.new "my-queue/example;{create:always}" + # # changes the subject to "test" + # addr.subject = "test" + # + def subject=(subject); @address_impl.setSubject(subject); end + + # Returns the type for the +Address+. + #-- + # We cannot use "type" since that clashes with the Ruby object.type + # identifier. + #++ + def address_type; @address_impl.getType; end + + # Sets the type for the +Address+. + # + # The type of the address determines how +Sender+ and +Receiver+ objects + # are constructed for it. It also affects how a reply-to address is + # encoded. + # + # If no type is specified then it will be determined by querying the + # broker. Explicitly setting the type prevents this. + # + # Values are either *queue* or *topic*. + # + # ==== Options + # + # * +type+ - the address type + # + # ==== Examples + # + # # creates an queue address + # addr = Qpid::Messaging::Address.new "my-queue;{create:always}" + # addr.address_type = "queue" + # + def address_type=(type); @address_impl.setType(type); end + + # Returns the options. + def options; @address_impl.getOptions; end + + # Sets the options for the address. + # + # *NOTE:* See the class documentation for more details on options. + # + # ==== Examples + # + # addr.options = :create => :always + # addr.options = :create => :always, :delete => :always + # + def options=(options = {}); @address_impl.setOptions(convert_options(options)); end + + def to_s # :nodoc: + @address_impl.str + end + + private + + def convert_options(options) + result = {} + options.each_pair {|key, value| result[key.to_s] = value.to_s} + + return result + end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/connection.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/connection.rb new file mode 100644 index 0000000000..6d637a1665 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/connection.rb @@ -0,0 +1,189 @@ +#-- +# 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 Qpid + + module Messaging + + # A +Connection+ represents a network connection to a remote endpoint. + class Connection + + attr_reader :options # :nodoc: + + # Creates a connection object. Raises a MessagingError if an invalid + # connection option is used. + # + # == Options + # + # * +:url+ - the URL for the broker + # * +:options+ - connection options + # + # == Controlling Reconnect Behavior + # + # The following connection options can be used to configure + # the reconnection behavior for this connection. + # + # * +:username+ - the authentication username + # * +:password+ - the authentication password + # * +:heartbeat+ + # * +:tcp_nodelay+ + # * +:sasl_mechanism+ + # * +:sasl_service+ + # * +:sasl_min_ssf+ + # * +:sasl_max_ssf+ + # * +:transport+ + # * +:reconnect+ - indicates whether to attempt reconnections + # * +:reconnect_timeout+ - the number of seconds to attempt reconnecting + # * +:reconnect_limit+ - the number of retries before reporting failure + # * +:reconnect_interval_min+ - initial delay, in seconds, before attempting a reconnection + # * +:reconnect_interval_max+ - number of seconds to wait before additional reconnect attempts + # * +:reconnect_interval+ - shorthand for setting both min and max values + # * +:reconnect_urls+ - a list of alternate URLs to use for reconnection attempts + # + # == Examples + # + # # creates a connection to the broker running local *localhost* + # conn = Qpid::Messaging::Connnection.new + # # creates a connection to *broker1.domain.com* on port *5672* + # conn = Qpid::Messaging::Connection.new :url => "amqp:tcp:broker1.domain.com:5672" + # # creates a connection to localhost with the specified authentication credentials + # conn = Qpid::Messaging::Connection.new :options => {:username => "login", :password => "password"} + # + def initialize(opts = {}) + @url = opts[:url] || "localhost" + @options = Qpid::Messaging.stringify(opts[:options] || {}) + @connection_impl = opts[:impl] || Cqpid::Connection.new(@url, @options) + end + + def connection_impl # :nodoc: + @connection_impl + end + + # Establishes the connection. + # + # == Examples + # + # # open a connection if it's not already open + # conn.open unless conn.open? + # + def open + @connection_impl.open + end + + # Reports whether the connection is open. + # + # == Examples + # + # # close the connection if it's not already closed + # conn.close if conn.open? + # + def open?; true && !@connection_impl.nil? && @connection_impl.isOpen; end + + # Closes the connection. + # + # == Examples + # + # # close a connection + # conn.close + # + def close; @connection_impl.close; end + + # Creates a new session. + # + # == Arguments + # + # * +:name+ - specifies the name for this session + # * +:transactional+ - if +true+ then a creates a transaction session (def. +false+) + # + # == Examples + # + # # create a session named 'session1' + # session = conn.create_session :name => "session1" + # # create a transactional session + # session = conn.create_session :transaction => true + # + def create_session(args = {}) + name = args[:name] || "" + if open? + if args[:transactional] + session = @connection_impl.createTransactionalSession name + else + session = @connection_impl.createSession name + end + return Session.new(self, session) + else + raise RuntimeError.new "No connection available." + end + end + + # Returns a Session with the given name. Raises an exception if no + # session with the given name exists. + # + # == Options + # + # * +name+ - the existing session's name + # + # == Examples + # + # # retrieve a session named 'mysession' from the current connection + # name = "my-session" + # # if no such session exists then catchh the exception raised + # begin + # session = conn.session name + # rescue MessagingException => error + # puts "No such session: #{name}." + # end + # + def session name + session_impl = @connection_impl.getSession name + Qpid::Messaging::Session.new self, session_impl if session_impl + end + + # Returns the username used to authenticate with the connection. + # + # If the connection did not user authentication credentials, then the + # username returned is "anonymous". + # + # == Examples + # + # # create a new connection for user "qpiduser" + # conn = Qpid::Messaging::Connection.new :username => "qpiduser" + # conn.open + # # displays the authenticate username + # puts "Connected as #{conn.authenticated_username}" # should say 'qpiduser' + # + def authenticated_username; @connection_impl.getAuthenticatedUsername if open?; end + + private + + def convert_options(options) + result = {} + unless options.nil? || options.empty? + options.each_pair {|key, value| result[key.to_s] = value.to_s} + end + + return result + end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/duration.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/duration.rb new file mode 100644 index 0000000000..11c903dade --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/duration.rb @@ -0,0 +1,128 @@ +#-- +# 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 Qpid + + module Messaging + + # A Duration represents a period of time in milliseconds + # + # == Named Durations + # + # The following named +Durations+ are available as symbols: + # + # [FOREVER] + # The maximum integer value for the platform. Effectively this will wait + # forever. + # + # [IMMEDIATE] + # An alias for 0 milliseconds. + # + # [SECOND] + # An alias for 1,000 milliseconds. + # + # [MINUTE] + # And alias for 60,000 millisecons. + # + class Duration + + # Creates a Duration with the specified length, in milliseconds. + # + # ==== Options + # + # * +length+ - The duration in +milliseconds+. + # + # ==== Examples + # + # # creates a duration of 15 seconds + # # REMEMBER: Duration deals in milliseconds + # delay = Qpid::Messaging::Duration.new 15000 + # + def initialize length + @duration_impl = Cqpid::Duration.new length + end + + def duration_impl # :nodoc: + @duration_impl + end + + # Returns the period of time in +milliseconds+. + # + # ==== Examples + # + # # doubling growth in waiting for messages in a loop + # do loop + # set the base duration waiting length + # timeout = Qpid::Messaging::Duration::SECOND + # msg = nil + # # loop until we receive a message + # while msg.nil? + # puts "Waiting #{timeout.milliseconds}ms" + # msg = recv.get timeout + # # if nothing was received, double the duration + # if msg.nil? + # # double out timeout + # timeout = timeout * 2 + # else + # # do something with the message + # puts "Received: #{msg.content}" + # end + # end + # end + # + def milliseconds + @duration_impl.getMilliseconds + end + + # Multiplies the duration of the +Duration+ and returns a new instance. + # + # Raises exceptions on a negative factor. Returns + # Qpid::Messaging::Duration::IMMEDIATE when the factor is 0. + # + # ==== Examples + # + # # return a duration that is 2 minutes (120,000 ms) + # twominutes = Qpid::Messaging::Duration::MINUTE * 2 + # + def *(factor) + raise TypeError.new "Factors must be non-zero positive values" if factor < 0 + return Qpid::Messaging::Duration::IMMEDIATE if factor.zero? + Qpid::Messaging::Duration.new((self.milliseconds * factor).floor) + end + + def self.add_item(key, value) # :nodoc: + @hash ||= {} + @hash[key] = Duration.new value + end + + def self.const_missing(key) # :nodoc: + @hash[key] + end + + self.add_item :FOREVER, Cqpid::Duration.FOREVER.getMilliseconds + self.add_item :IMMEDIATE, Cqpid::Duration.IMMEDIATE.getMilliseconds + self.add_item :SECOND, Cqpid::Duration.SECOND.getMilliseconds + self.add_item :MINUTE, Cqpid::Duration.MINUTE.getMilliseconds + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/encoding.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/encoding.rb new file mode 100644 index 0000000000..ac0fbc32a7 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/encoding.rb @@ -0,0 +1,75 @@ +#-- +# 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 Qpid + + module Messaging + + # Encodes the supplied content into the given message. + def self.encode content, message, encoding = nil # :nodoc: + Cqpid::encode content, message.message_impl, encoding + end + + # Decodes and returns the message's content. + def self.decode(message, content_type = nil) # :nodoc: + content_type = message.content_type if content_type.nil? + + case content_type + when "amqp/map" + return Cqpid.decodeMap message.message_impl + when "amqp/list" + return Cqpid.decodeList message.message_impl + end + + message.content + end + + # Takes as input any type and converts anything that's a symbol + # into a string. + def self.stringify(value) # :nodoc: + # set the default value + result = value + + case value + + when Symbol + result = value.to_s + + when Hash + result = {} + value.each_pair do |key, value| + result[stringify(key)] = stringify(value) + end + + when Array + result = [] + value.each do |element| + result << stringify(element) + end + + end + + return result + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/message.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/message.rb new file mode 100644 index 0000000000..e167800455 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/message.rb @@ -0,0 +1,353 @@ +#-- +# 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 Qpid + + module Messaging + + # A +Message+ represents an routable piece of information. + class Message + + # Creates a +Message+. + # + # ==== Options + # + # * +:content+ - the content + # + # ==== Examples + # + # # create a simple message and sends it + # message = Qpid::Messaging::Message.new :content => "This is a message." + # sender.send message + # + def initialize(args = {}) + @message_impl = (args[:impl] if args[:impl]) || nil + @message_impl = Cqpid::Message.new if @message_impl.nil? + @content = nil + args = {} if args.nil? + self.content = args[:content] if args[:content] + end + + def message_impl # :nodoc: + @message_impl + end + + # Sets the reply-to address. + # + # The address can either be an instance of Address or else and + # address string. + # + # ==== Options + # + # * +address+ - the address + # + # ==== Examples + # + # # set replies using an Address + # msg.reply_to = Qpid:Messaging::Address.new "my-responses" + # # set replies using an address string + # msg.reply_to = "my-feed/responses" + # + def reply_to=(address) + address = Qpid::Messaging::Address.new "#{address}" if !address.is_a? Qpid::Messaging::Address + + @message_impl.setReplyTo address.address_impl + end + + # Returns the reply to address for the +Message+. + def reply_to + address_impl = @message_impl.getReplyTo + # only return an address if a reply to was specified + Qpid::Messaging::Address.new(nil, address_impl) if address_impl + end + + # Sets the subject for the +Message+. + # + # ==== Options + # + # * +subject+ - the subject + def subject=(subject); @message_impl.setSubject subject; end + + # Returns the subject of the +Message+. + def subject; @message_impl.getSubject; end + + # Sets the content type for the +Message+. + # + # This should be set by the sending application and indicates to the + # recipients of the message how to interpret or decode the content. + # + # By default, only dictionaries and maps are automatically given a content + # type. If this content type is replaced then retrieving the content will + # not behave correctly. + # + # ==== Options + # + # * +content_type+ - the content type + # + # ==== Examples + # + # # send base64 encoded data in a mesage + # msg = Qpid::Messaging::Message.new :content = "UXBpZCBSdWxlcyEK" + # msg.content_type = "application/base64" + # + def content_type=(content_type); @message_impl.setContentType content_type; end + + # Returns the content type for the +Message+. + def content_type; @message_impl.getContentType; end + + # Sets the message id. + # + # *NOTE:* this field must be a UUID type currently. A non-UUID value will + # be converted to a zero UUID, though a blank ID will be left untouched. + # + # ==== Options + # + # * +id+ - the id + # + # ==== Examples + # + # # this example only works in Ruby >= 1.9, for 1.8 use a UUID library + # require 'SecureRandom' + # msg.message_id = SecureRandom.uuid + # + def message_id=(message_id); @message_impl.setMessageId message_id.to_s; end + + # Returns the message id. + def message_id; @message_impl.getMessageId; end + + # Sets the user id for the +Message+. + # + # This should in general be the user-id which was used when authenticating + # the connection itself, as the messaging infrastructure will verify + # this. + # + # See Qpid::Messaging::Connection.authenticated_username + # + # *NOTE:* If the id is not a +String+ then the id is set using + # the object's string representation. + # + # ==== Options + # + # * +id+ - the id + # + def user_id=(user_id); @message_impl.setUserId user_id; end + + # Returns the user id for the +Message+. + def user_id; @message_impl.getUserId; end + + # Sets the correlation id of the +Message+. + # + # The correlation id can be used as part of a protocol for message + # exchange patterns; e.g., a request-response pattern might require + # the correlation id of the request and the response to match, or it + # might use the message id of the request as the correlation id on + # the response. + # + # *NOTE:* If the id is not a +String+ then the id is setup using + # the object's string representation. + # + # ==== Options + # + # * +id+ - the id + # + def correlation_id=(correlation_id); @message_impl.setCorrelationId correlation_id; end + + # Returns the correlation id of the +Message+. + def correlation_id; @message_impl.getCorrelationId; end + + # Sets the priority of the +Message+. + # + # This may be used by the messaging infrastructure to prioritize + # delivery of messages with higher priority. + # + # *NOTE:* If the priority is not an integer type then it is set using + # the object's integer representation. If the integer value is greater + # than 8-bits then only the first 8-bits are used. + # + # ==== Options + # + # * +priority+ - the priority + # + def priority=(priority); @message_impl.setPriority priority; end + + # Returns the priority for the +Message+. + def priority; @message_impl.getPriority; end + + # Sets the time-to-live in milliseconds. + # + # This can be used by the messaging infrastructure to discard messages + # that are no longer of relevance. + # + # ==== Options + # + # * +duration+ - the number of milliseconds + # + def ttl=(duration) + if duration.is_a? Qpid::Messaging::Duration + @message_impl.setTtl duration.duration_impl + else + @message_impl.setTtl Cqpid::Duration.new duration.to_i + end + end + + # Returns the time-to-live in milliseconds. + def ttl; Qpid::Messaging::Duration.new @message_impl.getTtl.getMilliseconds; end + + # Sets the durability of the +Message+. + # + # This is a hint to the messaging infrastructure that the message + # should be persisted or otherwise stored. This helps to ensure + # that the message is not lost due to failures or a shutdown. + # + # ==== Options + # + # * +durable+ - the durability flag (def. false) + # + def durable=(durable); @message_impl.setDurable durable; end + + # Returns the durability for the +Message+. + def durable; @message_impl.getDurable; end + + # This is a hint to the messaging infrastructure that if de-duplication + # is required, that this message should be examined to determine if it + # is a duplicate. + # + # ==== Options + # + # * +redelivered+ - sets the redelivered state (def. false) + # + # ==== Examples + # + # # processed is a collection of messages already received + # msg.redelivered = true if processed.include? msg.message_id + # + def redelivered=(redelivered); @message_impl.setRedelivered redelivered; end + + # Returns whether the +Message+ has been marked as redelivered. + def redelivered; @message_impl.getRedelivered; end + + # Returns all named properties. + # + # *NOTE:* It is recommended to use the []= method for + # retrieving and setting properties. Using this method may + # result in non-deterministic behavior. + def properties; @message_impl.getProperties; end + + # Returns the value for the named property. + # + # ==== Options + # + # * +name+ - the property name + # + # ==== Examples + # + # # use of message properties to mark a message as digitally signed + # verify(msg) if msg[:signed] + # + def [](key); self.properties[key.to_s]; end + + # Assigns a value to the named property. + # + # A property's name or value, if a symbol, will be converted to a string + # representation. However, you will still be able to access them using + # a symbol for the name. + # + # ==== Options + # + # * +name+ - the property name + # * +value+ - the property value + # + # ==== Examples + # + # # set the signed attribute on a message and then retrieve it + # msg[:signed] = true # sets "signed" => true + # puts "It's signed" if msg["signed"] # outputs "It's signed" + # + def []=(key, value) + @message_impl.setProperty(key.to_s, + Qpid::Messaging.stringify(value)) + end + + # Sets the content for the +Message+. + # + # Content is automatically encoded for Array and Hash types. Other types + # need to set their own content types (via content_type) in order to + # specify how recipients should process the content. + # + # ==== Options + # + # * +content+ - the content + # + # ==== Examples + # + # # set a simple content for a message + # msg.content = "This is a simple message." + # # sets content that is automatically encoded + # msg.content = {:foo => :bar} + # + def content=(content) + content_type = nil + @content = Qpid::Messaging.stringify(content) + case @content + when Hash + content_type = "amqp/map" + when Array + content_type = "amqp/list" + end + if content_type.nil? + @message_impl.setContent @content + else + Qpid::Messaging.encode @content, self, content_type + end + end + + # Returns the content of the +Message+. + # + # Content is automatically decoded based on the specified content type. + # If the content type is application-specific, then no decoding is + # performed and the content is returnedas a +String+ representation. + # + # For example, if an array of integers are sent, then the receiver will + # find the message content to be an array of String objects, where each + # String is a representation of the sent integer value. + # + def content + if @content.nil? + @content = @message_impl.getContent + + # decode the content is necessary if it + # has an encoded content type + if ["amqp/list", "amqp/map"].include? @message_impl.getContentType + @content = Qpid::Messaging.decode(self, + @message_impl.getContentType) + end + + end + @content + end + + # Returns the content's size in bytes. + def content_size; @message_impl.getContentSize; end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/receiver.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/receiver.rb new file mode 100644 index 0000000000..05ee925212 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/receiver.rb @@ -0,0 +1,177 @@ +#-- +# 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 Qpid + + module Messaging + + # +Receiver+ is the entity through which messages are received. + # + # An instance of +Receiver+ can only be created using an active (i.e., not + # previously closed) Session. See Qpid::Messaging::Session.create_receiver + # for more details. + # + # ==== Example + # + # # create a connection and a session + # conn = Qpid::Messaging::Connection.new :url => "mybroker:5762" + # conn.open + # session = conn.create_session + # + # # create a receiver that listens on the "updates" topic of "alerts" + # receiver = session.create_receiver "alerts/updates" + # + # # wait for an incoming message and process it + # incoming = receiver.get Qpid::Messaging::Duration::FOREVER + # process(incoming) + # + class Receiver + + def initialize(session, receiver_impl) # :nodoc: + @session = session + @receiver_impl = receiver_impl + end + + def receiver_impl # :nodoc: + @receiver_impl + end + + # Retrieves a message from the local queue, or waits for up to + # the duration specified for one to become available. + # + # If no message is received within the specified time then a + # MessagingException is raised. + # + # ==== Options + # + # * duration - the timeout to wait + # + # ==== Examples + # + # # retrieves a message, also handles exceptions raised on no messages + # begin + # # checks for a message, returning immediately + # msg = recv.get Qpid::Messaging::Duration::IMMEDIATE + # puts "Received this message: #{message.content}" + # rescue + # puts "No messages available. + # end + # + def get(duration = Qpid::Messaging::Duration::FOREVER) + message_impl = @receiver_impl.get duration.duration_impl + create_message_wrapper message_impl unless message_impl.nil? + end + + # Retrieves a message from the receiver's subscription, or waits + # for up to the duration specified for one to become available. + # + # If no message is fetched within the specified time then a + # MessagingException is raised. + # + # ==== Options + # + # * duration - the timeout to wait (def. Duration::FOREVER) + # + # ==== Examples + # + # # retrieves a message, also handles exceptions raised on no messages + # begin + # # checks for a message, times out after one second + # msg = recv.fetch Qpid::Messaging::Duration::SECOND + # puts "Fetched this message: #{message.content}" + # rescue + # puts "No messages available. + # end + # + def fetch(duration = Qpid::Messaging::Duration::FOREVER) + message_impl = @receiver_impl.fetch duration.duration_impl + create_message_wrapper message_impl unless message_impl.nil? + end + + # Sets the capacity. + # + # The capacity of a +Receiver+ is the number of Messages that can be + # pre-fetched from the broker and held locally. If capacity is 0 then + # messages will never be pre-fetched and all messages must instead be + # retrieved using #fetch. + # + # ==== Options + # + # * capacity - the capacity + # + # ==== Examples + # + # # create a receiver and give it a capacity of 50 + # recv = session.create_receiver "alerts/minor" + # recv.capacity = 50 + # + def capacity=(capacity); @receiver_impl.setCapacity capacity; end + + # Returns the capacity. + def capacity; @receiver_impl.getCapacity; end + + # Returns the number of messages locally held. + # + # The available is always 0 <= available <= capacity. + # + # If the #capacity is set to 0 then available will always be 0. + # + # ==== Examples + # + # # output the number of messages waiting while processing + # loop do + # puts "There are #{recv.available} messages pending..." + # # wait forever (the default) for the next message + # msg = recv.get + # # process the message + # dispatch_message msg + # end + # + def available; @receiver_impl.getAvailable; end + + # Returns the number of messages that have been received and acknowledged + # but whose acknowledgements have not been confirmed by the sender. + def unsettled; @receiver_impl.getUnsettled; end + + # Closes this +Receiver+. + # + # This does not affect the owning Session or Connection. + def close; @receiver_impl.close; end + + # Returns whether the +Receiver+ is closed. + def closed?; @receiver_impl.isClosed; end + + # Returns the name of this +Receiver+. + def name; @receiver_impl.getName; end + + # Returns the owning Session for this +Receiver+. + def session; @session; end + + private + + def create_message_wrapper message_impl # :nodoc: + Qpid::Messaging::Message.new(:impl => message_impl) + end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/sender.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/sender.rb new file mode 100644 index 0000000000..4ce1393dc7 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/sender.rb @@ -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. +#++ + +module Qpid + + module Messaging + + # +Sender+ is the entity through which messages are sent. + # + # An instance of +Sender+ can only be created using an active (not previously + # closed) Session. See Qpid::Messaging::Session.create_sender for more details. + # + # ==== Examples + # + # # create a connection + # conn = Qpid::Messaging::Connection.new "mybroker:5672" + # conn.open + # + # if conn.open? + # + # # create a session + # session = conn.create_session + # + # # create a sender that posts messages to the "updates" queue + # sender = session.create_sender "updates;{create:always} + # + # # begin sending updates + # loop do + # # wait for the next event content then send it + # content = wait_for_event + # sender.send Qpid::Messaging::Message.new :content => content + # end + # end + # + class Sender + + def initialize(session, sender_impl) # :nodoc: + @session = session + @sender_impl = sender_impl + end + + def sender_impl # :nodoc: + @sender_impl + end + + # Sends a message, optionally blocking until the message is received + # by the broker. + # + # ==== Options + # + # * +message+ - The message to send. + # * +:sync+ - Block until received. See note below on synching. + # + # ==== Synching + # + # If :sync => true, then the call will block until the broker confirms + # receipt of the message. Otherwise it will only block for available + # capacity; i.e., until pending is equal to capacity. + # + # ==== Examples + # + # # send a message + # outgoing = Qpid::Messaging::Message.new :content => content + # sender.send outgoing + # + # # send a message, wait for confirmation from the broker + # outgoing = Qpid::Messaging::Message.new :content => content + # sender.send outgoing, :sync => true + # + def send(message, args = {}, &block) + sync = args[:sync] || false + @sender_impl.send message.message_impl, sync + block.call message unless block.nil? + end + + # Closes this +Sender+. + # + # This does not affect the owning Session or Connection. + def close; @sender_impl.close; end + + # Returns the human-readable name for this +Sender+. + def name; @sender_impl.getName; end + + # Sets the capacity for this +Sender+. + # + # The capacity is the number of outgoing messages that can be held + # pending confirmation of receipt by the broker. + # + # ==== Options + # + # * +capacity+ - the capacity + def capacity=(capacity); @sender_impl.setCapacity capacity; end + + # Returns the capacity. + def capacity; @sender_impl.getCapacity; end + + # Returns the number of messages sent that are pending receipt + # confirmation by the broker. + def unsettled; @sender_impl.getUnsettled; end + + # Returns the available slots for sending messages. + # + # This differs from +capacity+ in that it is the available slots in + # the senders capacity for holding outgoing messages. The difference + # between capacity and available is the number of messages that + # have not been delivered yet. + def available + @sender_impl.getAvailable + end + + # Returns the Session for this sender. + def session; @session; end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/lib/qpid_messaging/session.rb b/cpp/bindings/qpid/ruby/lib/qpid_messaging/session.rb new file mode 100644 index 0000000000..7e6e11f654 --- /dev/null +++ b/cpp/bindings/qpid/ruby/lib/qpid_messaging/session.rb @@ -0,0 +1,264 @@ +#-- +# 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 Qpid + + module Messaging + + # A +Session+ represents a distinct conversation between end points. They are + # created from an active (i.e., not closed) Connection. + # + # A +Session+ is used to acknowledge individual or all messages that have + # passed through it + class Session + + def initialize(connection, session) # :nodoc: + @connection = connection + @session_impl = session + end + + def session_impl # :nodoc: + @session_impl + end + + # Returns the Connection associated with this session. + def connection + @connection + end + + # Creates a new endpoint for sending messages. + # + # The address can either be an instance Address or else an + # address string. + # + # ==== Arguments + # + # * +address+ - the end point address. + def create_sender(address) + _address = address + + if address.class == Qpid::Messaging::Address + _address = address.address_impl + end + + sender_impl = @session_impl.createSender(_address) + sender_name = sender_impl.getName + + Qpid::Messaging::Sender.new(self, sender_impl) + end + + # Retrieves the Sender with the specified name. + # + # Raises an exception if no such Sender exists. + # + # ==== Arguments + # + # * +name+ - the name of the Sender + def sender(name) + Qpid::Messaging::Sender.new self, @session_impl.getSender(name) + end + + # Creates a new endpoint for receiving messages. + # + # The +address+ can either be an instance Address or else an + # address string. + # + # ==== Arguments + # + # * +address+ - the end point address. + def create_receiver(address) + result = nil + receiver_impl = nil + + if address.class == Qpid::Messaging::Address + address_impl = address.address_impl + receiver_impl = @session_impl.createReceiver address_impl + else + receiver_impl = @session_impl.createReceiver(address) + end + + Qpid::Messaging::Receiver.new self, receiver_impl + end + + # Retrieves the +Receiver+ with the specified name, or nil if no such + # Receiver exists. + # + # ==== Arguments + # + # * +name+ - the name of the Receiver + def receiver(name) + Qpid::Messaging::Receiver.new self, @session_impl.getReceiver(name) + end + + # Closes the +Session+ and all associated +Sender+ and +Receiver+ instances. + # + # *NOTE:* All +Session+ instances for a Connection are closed when the + # Connection is closed. But closing a +Session+ does not affect the + # owning Connection. + def close; @session_impl.close; end + + # Commits any pending transactions for a transactional session. + def commit; @session_impl.commit; end + + # Rolls back any uncommitted transactions on a transactional session. + def rollback; @session_impl.rollback; end + + # Acknowledges one or more outstanding messages that have been received + # on this session. + # + # ==== Arguments + # + # * +options+ - the set of options + # + # ==== Options + # + # * :message - if specified, then only that Message is acknowledged + # * :sync - if true, the call will block until processed by the broker + # + # ==== Examples + # + # # acknowledge all received messages + # session.acknowledge + # + # # acknowledge a single message + # session.acknowledge :message => message + # + # # acknowledge all messages, wait until the call finishes + # session.acknowledge :sync => true + # + #-- + # TODO: Add an optional block to be used for blocking calls. + #++ + def acknowledge(options = {}) + sync = options[:sync] || false + message = options[:message] if options[:message] + + unless message.nil? + @session_impl.acknowledge message.message_impl, sync + else + @session_impl.acknowledge sync + end + end + + # Rejects the specified message. A rejected message will not be + # redelivered. + # + # NOTE: A message cannot be rejected once it has been acknowledged. + def reject(message); @session_impl.reject message.message_impl; end + + # Releases the message, which allows the broker to attempt to + # redeliver it. + # + # NOTE: A message connot be released once it has been acknowled. + def release(message); @session_impl.release message.message_impl; end + + # Requests synchronization with the broker. + # + # ==== Arguments + # + # * +options+ - the list of options + # + # ==== Options + # + # * +:block+ - if true, the call blocks until the broker acknowledges it + # + #-- + # TODO: Add an optional block to be used for blocking calls. + #++ + def sync(args = {}) + block = args[:block] || false + @session_impl.sync block + end + + # Returns the total number of receivable messages, and messages already + # received, by Receiver instances associated with this +Session+. + def receivable; @session_impl.getReceivable; end + + # Returns the number of messages that have been acknowledged by this + # +Session+ whose acknowledgements have not been confirmed as processed + # by the broker. + def unsettled_acks; @session_impl.getUnsettledAcks; end + + # Fetches the next Receiver with a message pending. Waits the specified + # number of milliseconds before timing out. + # + # For a Receiver to be returned, it must have a capacity > 0 and have + # Messages locally queued. + # + # If no Receiver is found within the time out period, then a MessageError + # is raised. + # + # ==== Arguments + # + # * +timeout+ - the duration + # + # ==== Examples + # + # loop do + # + # begin + # # wait a maximum of one minute for the next receiver to be ready + # recv = session.next_receiver Qpid::Messaging::Duration::MINUTE + # + # # get and dispatch the message + # msg = recv.get + # dispatch_message msg + # + # rescue + # puts "No receivers were returned" + # end + # + # end + def next_receiver(timeout = Qpid::Messaging::Duration::FOREVER, &block) + receiver_impl = @session_impl.nextReceiver(timeout.duration_impl) + + unless receiver_impl.nil? + recv = Qpid::Messaging::Receiver.new self, receiver_impl + block.call recv unless block.nil? + end + + return recv + end + + # Returns true if there were exceptions on this session. + def errors?; @session_impl.hasError; end + + # If the +Session+ has been rendered invalid due to some exception, + # this method will result in that exception being raised. + # + # If none have occurred, then no exceptions are raised. + # + # ==== Examples + # + # # show any errors that occurred during the Session + # if @session.errors? + # begin + # @session.errors + # rescue Exception => error + # puts "An error occurred: #{error}" + # end + # end + def errors; @session_impl.checkError; end + + end + + end + +end + diff --git a/cpp/bindings/qpid/ruby/qpid_messaging.gemspec b/cpp/bindings/qpid/ruby/qpid_messaging.gemspec new file mode 100644 index 0000000000..06e3f48cb8 --- /dev/null +++ b/cpp/bindings/qpid/ruby/qpid_messaging.gemspec @@ -0,0 +1,28 @@ +# -*- encoding: utf-8 -*- +lib = File.expand_path('lib/', __FILE__) +$:.unshift lib unless $:.include?(lib) + +# Generate the Swig wrapper +system "swig -ruby -c++ -I../../../include -I../../ -o ext/cqpid/cqpid.cpp ruby.i" + +Gem::Specification.new do |s| + s.name = "qpid_messaging" + s.version = "0.22.0" + s.platform = Gem::Platform::RUBY + s.authors = "Apache Qpid Project" + s.email = "dev@qpid.apache.org" + s.homepage = "http://qpid.apache.org" + s.summary = "Qpid is an enterprise messaging framework." + s.description = s.summary + + s.extensions = "ext/cqpid/extconf.rb" + s.files = Dir["LICENSE", + "ChangeLog", + "README.rdoc", + "TODO", + "lib/**/*.rb", + "ext/**/*", + ] + s.require_path = 'lib' +end + diff --git a/cpp/bindings/qpid/ruby/ruby.i b/cpp/bindings/qpid/ruby/ruby.i index 76463f7ddd..3d686c2ddb 100644 --- a/cpp/bindings/qpid/ruby/ruby.i +++ b/cpp/bindings/qpid/ruby/ruby.i @@ -18,8 +18,10 @@ */ %module cqpid +/* Ruby doesn't have a != operator*/ +#pragma SWIG nowarn=378 %include "std_string.i" -%include "../../swig_ruby_typemaps.i" +%include "qpid/swig_ruby_typemaps.i" /* Define the general-purpose exception handling */ %exception { @@ -32,5 +34,5 @@ } } -%include "../qpid.i" +%include "qpid/qpid.i" diff --git a/cpp/bindings/qpid/ruby/spec/qpid/address_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/address_spec.rb deleted file mode 100644 index 784fb6fe77..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/address_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Address do - - before(:each) do - @address = Qpid::Messaging::Address.new "my-name", "my-subject", :create => :always - end - - it "stores the name, subject and options when created" do - name = @address.name - subject = @address.subject - create = @address.options["create"] - - name.should == "my-name" - subject.should == "my-subject" - create.should == "always" - end - - it "can update the name" do - @address.name = "new-name" - - name = @address.name - - name.should == "new-name" - end - - it "can update the subject" do - @address.subject = "new-subject" - - subject = @address.subject - - subject.should == "new-subject" - end - - it "can update the type" do - @address.address_type = "routed" - - type = @address.address_type - - type.should == "routed" - end - - it "can update the options" do - @address.options[:create] = :never - - create = @address.options["create"] - - create.should == "always" - end - - it "can return a string representation" do - address = Qpid::Messaging::Address.new "foo", "bar", :create => :always, :link => :durable - result = address.to_s - - result.should =~ /foo\/bar/ - result.should =~ /create:always/ - result.should =~ /link:durable/ - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/connection_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/connection_spec.rb deleted file mode 100644 index a2f5b7e898..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/connection_spec.rb +++ /dev/null @@ -1,191 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Connection do - - before(:each) do - @session_impl = double('Cqpid::Session') - @connection_impl = double('Cqpid::Connection') - - @connection = Qpid::Messaging::Connection.new :impl => @connection_impl - end - - it "accepts options on construction" do - expect { - connection = Qpid::Messaging::Connection.new :options => {:username => "foo"} - - connection.options.should include("username") - }.should_not raise_error - end - - it "returns the underlying implementation" do - impl = @connection.connection_impl - - impl.should == @connection_impl - end - - it "opens the connection" do - @connection_impl.should_receive(:open) - - @connection.open - end - - it "closes the connection" do - @connection_impl.should_receive(:close) - - @connection.close - end - - it "retrieves a session by name" do - @connection_impl.should_receive(:getSession). - with("farkle"). - and_return(@session_impl) - - session = @connection.session "farkle" - - session.session_impl.should == @session_impl - end - - it "raises an error when a session name is invalid" do - @connection_impl.should_receive(:getSession). - with("farkle"). - and_raise(RuntimeError) - - expect { - @connection.session "farkle" - }.to raise_error(SessionNameException) - end - - #################################################################### - # test conditions for when a connection is not connected to a broker - #################################################################### - describe "when closed" do - - before(:each) do - @connection_impl.should_receive(:isOpen). - and_return(false) - end - - it "returns false when not connected to a broker" do - open = @connection.open? - - open.should == false - end - - it "should raise an error when creating a session on a closed connection" do - expect { - @connection.create_session - }.to raise_error(RuntimeError) - end - - it "raises an error when creating a transactional session on a closed connection" do - expect { - @connection.create_session :transactional => true - }.to raise_error(RuntimeError) - end - - it "raises an error when creating a named session on a closed connection" do - expect { - @connection.create_session :name => "test", :transactional => true - }.to raise_error(RuntimeError) - end - - it "returns a null username when not connected" do - username = @connection.authenticated_username - - username.should be_nil - end - - end - - ######################################################### - # test conditions for when a connection must be connected - ######################################################### - describe "when connected" do - - before(:each) do - @connection_impl.should_receive(:isOpen). - and_return(true) - end - - it "returns true when connected to a broker" do - open = @connection.open? - - open.should == true - end - - it "creates a session" do - @connection_impl.should_receive(:createSession). - and_return(@session_impl) - - session = @connection.create_session - - session.session_impl.should == @session_impl - end - - it "creates a named session with a name when provided" do - @connection_impl.should_receive(:createSession).with("farkle"). - and_return(@session_impl) - - session = @connection.create_session :name => "farkle" - - session.session_impl.should == @session_impl - end - - it "creates a transactional session when specified" do - @connection_impl.should_receive(:createTransactionalSession). - and_return(@session_impl) - - session = @connection.create_session :transactional => true - - session.session_impl.should == @session_impl - end - - it "creates a named transactional session when specified" do - @connection_impl.should_receive(:createTransactionalSession). - with("farkle"). - and_return(@session_impl) - - session = @connection.create_session :transactional => true, :name => "farkle" - - session.session_impl.should == @session_impl - end - - it "returns the authenticated username when connected" do - @connection_impl.should_receive(:getAuthenticatedUsername). - and_return("mcpierce") - - username = @connection.authenticated_username - - username.should == "mcpierce" - end - - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/duration_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/duration_spec.rb deleted file mode 100644 index 4980b6ffe7..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/duration_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Duration do - - before(:each) do - @duration = Qpid::Messaging::Duration::SECOND - end - - it "returns the underlying implementation" do - impl = @duration.duration_impl - - impl.should_not be_nil - end - - it "can create a duration with a millisecond value" do - duration = Qpid::Messaging::Duration.new 500 - - milliseconds = duration.milliseconds - - milliseconds.should == 500 - end - - it "returns the time in milliseconds" do - milliseconds = @duration.milliseconds - - milliseconds.should == 1000 - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/encoding_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/encoding_spec.rb deleted file mode 100644 index 58b8447278..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/encoding_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe "encoding" do - end - - describe "decoding" do - - before(:each) do - @message = Qpid::Messaging::Message.new - end - - it "can decode a message's text content" do - @message.content = "This is an unencoded message." - - content = Qpid::Messaging.decode @message - - content.should == "This is an unencoded message." - end - - it "can decode a message's list content" do - @message.content = ["this", "that"] - - content = Qpid::Messaging.decode @message - - content.should == ["this", "that"] - end - - it "can decode a message's map content" do - @message.content = {"this" => "that"} - - content = Qpid::Messaging.decode @message - - content.should == {"this" => "that"} - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/message_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/message_spec.rb deleted file mode 100644 index e34e58f563..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/message_spec.rb +++ /dev/null @@ -1,292 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Message do - - before(:each) do - @message = Qpid::Messaging::Message.new :content => "My content" - end - - it "returns its implementation" do - impl = @message.message_impl - - impl.class.should == Cqpid::Message - end - - it "can set the reply to address" do - address = Qpid::Messaging::Address.new "my-queue", "" - - @message.reply_to = address - - reply_to = @message.reply_to - - reply_to.name.should == address.name - end - - it "should store the content when created" do - content = @message.content - - content.should == "My content" - end - - it "should properly encode a map when created" do - message = Qpid::Messaging::Message.new :content => {"foo" => "bar"} - - content = message.content - content_type = message.content_type - - content_type.should == "amqp/map" - content.class == Hash - content["foo"].should == "bar" - end - - it "should properly encode a list when created" do - message = Qpid::Messaging::Message.new :content => ["foo", "bar"] - - content = message.content - content_type = message.content_type - - content_type.should == "amqp/list" - content.class == Array - content.should include("foo") - content.should include("bar") - end - - it "should store the subject" do - @message.subject = "new-subject" - - subject = @message.subject - - subject.should == "new-subject" - end - - it "should update the content type" do - @message.content_type = "amqp/audio" - - content_type = @message.content_type - - content_type.should == "amqp/audio" - end - - it "should store the message id" do - @message.message_id = "foo" - - id = @message.message_id - - id.should == "foo" - end - - it "should store the user id" do - @message.user_id = "foo" - - id = @message.user_id - - id.should == "foo" - end - - it "should store the correlation id" do - @message.correlation_id = "message1" - - id = @message.correlation_id - - id.should == "message1" - end - - it "should store the priority" do - @message.priority = 7 - - priority = @message.priority - - priority.should == 7 - end - - it "should accept a Duration as the time to live" do - @message.ttl = Qpid::Messaging::Duration::SECOND - - ttl = @message.ttl - - ttl.milliseconds.should == Qpid::Messaging::Duration::SECOND.milliseconds - end - - it "should accept an integer value as the time to live" do - @message.ttl = 15000 - - ttl = @message.ttl - - ttl.milliseconds.should == 15000 - end - - it "should update the durable flag" do - @message.durable = true - - durable = @message.durable - - durable.should == true - end - - it "should update the redelivered flag" do - @message.redelivered = true - - redelivered = @message.redelivered - - redelivered.should == true - end - - it "should store a property" do - property = @message[:test_property] - - property.should == nil - - @message[:test_property] = "test_value1" - - property = @message[:test_property] - - property.should == "test_value1" - end - - it "should convert a symbol property value to a string" do - @message[:test_property] = :test_value2 - - property = @message[:test_property] - - property.should == "test_value2" - end - - it "should convert a symbol property name to a string" do - @message[:test_property] = "test_value3" - - property = @message["test_property"] - - property.should == "test_value3" - end - - it "should store text content" do - @message.content = "This is the content." - - content = @message.content - - content.should == "This is the content." - end - - it "should store list content" do - list = ["foo", "bar"] - - @message.content = list - - content = @message.content - content_type = @message.content_type - - content.should == list - content_type.should == "amqp/list" - end - - it "should convert symbol list elements to strings" do - @message.content = [:farkle] - - content = @message.content.first - - content.should == "farkle" - end - - it "should store map content" do - map = {"foo" => "bar"} - - @message.content = map - - content = @message.content - content_type = @message.content_type - - content.should == map - content_type.should == "amqp/map" - end - - it "should convert symbol map elements to strings" do - @message.content = {:first_name => :qpid} - - content = @message.content["first_name"] - - content.should == "qpid" - end - - describe "with content from the underlying implementation" do - - before(:each) do - @message_impl = double("Cqpid::Message") - @message = Qpid::Messaging::Message.new :impl => @message_impl - end - - it "should return simple text content" do - @message_impl.should_receive(:getContent). - and_return("my content") - @message_impl.should_receive(:getContentType). - and_return("") - - content = @message.content - - content.should == "my content" - end - - it "should decode a list" do - list = ["first", "second"] - - @message_impl.should_receive(:getContent). - and_return(list) - @message_impl.should_receive(:getContentType). - twice. - and_return("amqp/list") - Qpid::Messaging.stub!(:decode). - with(@message, "amqp/list"). - and_return(list) - - content = @message.content - - content.should == list - end - - it "should decode a map" do - map = {"first" => "second"} - - @message_impl.should_receive(:getContent). - and_return(map) - @message_impl.should_receive(:getContentType). - twice. - and_return("amqp/map") - Qpid::Messaging.stub!(:decode). - with(@message, "amqp/map"). - and_return(map) - - content = @message.content - - content.should == map - end - - - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/receiver_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/receiver_spec.rb deleted file mode 100644 index 81ae935dcb..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/receiver_spec.rb +++ /dev/null @@ -1,170 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Receiver do - - before(:each) do - @message_impl = double("Cqpid::Message") - @session = double("Qpid::Messaging::Session") - @receiver_impl = double("Cqpid::Receiver") - - @receiver = Qpid::Messaging::Receiver.new @session, @receiver_impl - end - - it "returns the underlying implementation" do - impl = @receiver.receiver_impl - - impl.should == @receiver_impl - end - - it "gets a message with the default duration" do - @receiver_impl.should_receive(:get). - with(Qpid::Messaging::Duration::FOREVER.duration_impl). - and_return(@message_impl) - - message = @receiver.get - - message.message_impl.should == @message_impl - end - - it "gets a message with a specified duration" do - @receiver_impl.should_receive(:get). - with(Qpid::Messaging::Duration::SECOND.duration_impl). - and_return(@message_impl) - - message = @receiver.get Qpid::Messaging::Duration::SECOND - - message.message_impl.should == @message_impl - end - - it "returns nil when get receives no message" do - @receiver_impl.should_receive(:get). - with(Qpid::Messaging::Duration::MINUTE.duration_impl). - and_return(nil) - - message = @receiver.get Qpid::Messaging::Duration::MINUTE - - message.should be_nil - end - - it "fetches a message with the default duration" do - @receiver_impl.should_receive(:fetch). - with(Qpid::Messaging::Duration::FOREVER.duration_impl). - and_return(@message_impl) - - message = @receiver.fetch - - message.message_impl.should == @message_impl - end - - it "fetches a message with a specified duration" do - @receiver_impl.should_receive(:fetch). - with(Qpid::Messaging::Duration::SECOND.duration_impl). - and_return(@message_impl) - - message = @receiver.fetch Qpid::Messaging::Duration::SECOND - - message.message_impl.should == @message_impl - end - - it "returns nil when fetch recieves no message" do - @receiver_impl.should_receive(:fetch). - with(Qpid::Messaging::Duration::MINUTE.duration_impl). - and_return(nil) - - message = @receiver.fetch Qpid::Messaging::Duration::MINUTE - - message.should be_nil - end - - it "assigns capacity" do - @receiver_impl.should_receive(:setCapacity). - with(10) - - @receiver.capacity = 10 - end - - it "returns the capacity" do - @receiver_impl.should_receive(:getCapacity). - and_return(10) - - capacity = @receiver.capacity - - capacity.should == 10 - end - - it "reports the number of available messages" do - @receiver_impl.should_receive(:getAvailable). - and_return(20) - - available = @receiver.available - - available.should == 20 - end - - it "reports the number of unsettled messages" do - @receiver_impl.should_receive(:getUnsettled). - and_return(25) - - unsettled = @receiver.unsettled - - unsettled.should == 25 - end - - it "closes" do - @receiver_impl.should_receive(:close) - - @receiver.close - end - - it "reports its closed status" do - @receiver_impl.should_receive(:isClosed). - and_return(true) - - closed = @receiver.closed? - - closed.should == true - end - - it "returns its name" do - @receiver_impl.should_receive(:getName). - and_return("farkle") - - name = @receiver.name - - name.should == "farkle" - end - - it "returns its related session" do - session = @receiver.session - - session.should == @session - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/sender_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/sender_spec.rb deleted file mode 100644 index fa3a2a5b1f..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/sender_spec.rb +++ /dev/null @@ -1,135 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Sender do - - before(:each) do - @message = double("Qpid::Messaging::Message") - @message_impl = double("Cqpid::Message") - @sender_impl = double("Cqpid::Sender") - @session = double("Qpid::Messaging::Session") - - @sender = Qpid::Messaging::Sender.new @session, @sender_impl - end - - it "returns its implementation" do - impl = @sender.sender_impl - - impl.should == @sender_impl - end - - it "sends a message" do - @message.should_receive(:message_impl). - and_return(@message_impl) - @sender_impl.should_receive(:send). - with(@message_impl, false) - - @sender.send @message - end - - it "sends a message with optional synch" do - @message.should_receive(:message_impl). - and_return(@message_impl) - @sender_impl.should_receive(:send). - with(@message_impl, true) - - @sender.send @message, :sync => true - end - - it "sends a message with an optional block" do - block_called = false - - @message.should_receive(:message_impl). - and_return(@message_impl) - @sender_impl.should_receive(:send). - with(@message_impl, false) - - @sender.send @message do |message| - block_called = true if message == @message - end - - block_called.should be_true - end - - it "closes" do - @sender_impl.should_receive(:close) - - @sender.close - end - - it "returns its name" do - @sender_impl.should_receive(:getName). - and_return("farkle") - - name = @sender.name - - name.should == "farkle" - end - - it "sets its capacity" do - @sender_impl.should_receive(:setCapacity). - with(100) - - @sender.capacity = 100 - end - - it "returns its capacity" do - @sender_impl.should_receive(:getCapacity). - and_return(25) - - capacity = @sender.capacity - - capacity.should == 25 - end - - it "returns the number of unsettled messages" do - @sender_impl.should_receive(:getUnsettled). - and_return(15) - - unsettled = @sender.unsettled - - unsettled.should == 15 - end - - it "returns the number of available message slots" do - @sender_impl.should_receive(:getAvailable). - and_return(50) - - available = @sender.available - - available.should == 50 - end - - it "returns a reference to its session" do - session = @sender.session - - session.should == @session - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid/session_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid/session_spec.rb deleted file mode 100644 index 0b103a31e6..0000000000 --- a/cpp/bindings/qpid/ruby/spec/qpid/session_spec.rb +++ /dev/null @@ -1,353 +0,0 @@ -# -# 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. -# - -require 'spec_helper' - -module Qpid - - module Messaging - - describe Session do - - before(:each) do - @connection = double("Qpid::Messaging::Connection") - @session_impl = double("Cqpid::Session") - @session = Qpid::Messaging::Session.new @connection, @session_impl - @sender_impl = double("Cqpid::Sender") - @receiver_impl = double("Cqpid::Receiver") - end - - it "returns its implementation" do - impl = @session.session_impl - - impl.should == @session_impl - end - - it "returns its connection" do - connection = @session.connection - - connection.should == @connection - end - - it "creates a Sender from an Address" do - address = Qpid::Messaging::Address.new "my-queu", "", :create => :always - - @session_impl.should_receive(:createSender). - with(address.address_impl). - and_return(@sender_impl) - @sender_impl.should_receive(:getName). - and_return("my-queue") - - sender = @session.create_sender address - - sender.sender_impl.should == @sender_impl - end - - it "creates a Sender from an address string" do - address = "my-queue;{create:true}" - - @session_impl.should_receive(:createSender). - with(address). - and_return(@sender_impl) - @sender_impl.should_receive(:getName). - and_return("my-queue") - - sender = @session.create_sender address - - sender.sender_impl.should == @sender_impl - end - - ####################################### - # scenarios involing an existing Sender - ####################################### - describe "when retrieving a Sender by name" do - - before(:each) do - address = "my-queue;{create:always}" - @name = "my-queue" - - @session_impl.should_receive(:createSender). - with(address). - and_return(@sender_impl) - @sender_impl.should_receive(:getName). - and_return(@name) - - @sender = @session.create_sender address - end - - it "works when the name is valid" do - sender = @session.sender @name - - sender.should == @sender - end - - it "raises an error when the name is invalid" do - expect { - @session.sender @name.reverse - }.to raise_error(Qpid::Messaging::KeyError) - end - - end - - it "creates a Receiver from an Address" do - address = Qpid::Messaging::Address.new "my-queue", "" - - @session_impl.should_receive(:createReceiver). - with(address.address_impl). - and_return(@receiver_impl) - @receiver_impl.should_receive(:getName). - and_return("my-queue") - - receiver = @session.create_receiver address - - receiver.receiver_impl.should == @receiver_impl - end - - it "creates a Receiver from an address string" do - address = "my-queue" - - @session_impl.should_receive(:createReceiver). - with(address). - and_return(@receiver_impl) - @receiver_impl.should_receive(:getName). - and_return("my-queue") - - receiver = @session.create_receiver address - - receiver.receiver_impl.should == @receiver_impl - end - - ######################################### - # scenarios involving an existing Receiver - ########################################## - describe "when retrieving a Receiver by name" do - - before(:each) do - address = "my-queue" - @name = "my-queue" - - @session_impl.should_receive(:createReceiver). - with(address). - and_return(@receiver_impl) - @receiver_impl.should_receive(:getName). - and_return(@name) - - @receiver = @session.create_receiver address - end - - it "works with a valid name" do - receiver = @session.receiver @name - - receiver.should == @receiver - end - - it "raises an error when the name is invalid" do - expect { - @session.receiver @name.reverse - }.to raise_error(Qpid::Messaging::KeyError) - end - - end - - it "closes the session" do - @session_impl.should_receive(:close) - - @session.close - end - - it "commits a pending transaction" do - @session_impl.should_receive(:commit) - - @session.commit - end - - it "rolls back an uncommitted transaction" do - @session_impl.should_receive(:rollback) - - @session.rollback - end - - it "acknowledges all received messages" do - @session_impl.should_receive(:acknowledge). - with(false) - - @session.acknowledge - end - - it "acknowledges all messages synchronously" do - @session_impl.should_receive(:acknowledge). - with(true) - - @session.acknowledge :sync => true - end - - it "acknowledges all messages asynchronously" do - @session_impl.should_receive(:acknowledge). - with(false) - - @session.acknowledge :sync => false - end - - ###################################### - # Scenarios involving a single message - ###################################### - describe "with a single message" do - - before(:each) do - @message = Qpid::Messaging::Message.new :content => "Testing" - end - - it "can acknowledge asynchronously by default" do - @session_impl.should_receive(:acknowledge). - with(@message.message_impl, false) - - @session.acknowledge :message => @message - end - - it "can acknowledge synchronously" do - @session_impl.should_receive(:acknowledge). - with(@message.message_impl, true) - - @session.acknowledge :message => @message, :sync => true - end - - it "can acknowledge asynchronously" do - @session_impl.should_receive(:acknowledge). - with(@message.message_impl, false) - - @session.acknowledge :message => @message, :sync => false - end - - it "can reject it" do - @session_impl.should_receive(:reject). - with(@message.message_impl) - - @session.reject @message - end - - it "can release it" do - @session_impl.should_receive(:release). - with(@message.message_impl) - - @session.release @message - end - - end - - it "does not block by default when synchronizating with the broker" do - @session_impl.should_receive(:sync). - with(false) - - @session.sync - end - - it "can block while synchronizing with the broker" do - @session_impl.should_receive(:sync). - with(true) - - @session.sync :block => true - end - - it "can not block while synchronizing with the broker" do - @session_impl.should_receive(:sync). - with(false) - - @session.sync :block => false - end - - it "returns the number of messages that are receivable" do - @session_impl.should_receive(:getReceivable). - and_return(15) - - receivable = @session.receivable - - receivable.should == 15 - end - - it "returns the number of unsettled messages" do - @session_impl.should_receive(:getUnsettledAcks). - and_return(25) - - unsettled = @session.unsettled_acks - - unsettled.should == 25 - end - - it "waits forever by default for the next Receiver with messages" do - @session_impl.should_receive(:nextReceiver). - with(Qpid::Messaging::Duration::FOREVER.duration_impl). - and_return(@receiver_impl) - - receiver = @session.next_receiver - - receiver.receiver_impl.should == @receiver_impl - end - - it "uses the specified time when waiting for the next Receiver with messages" do - @session_impl.should_receive(:nextReceiver). - with(Qpid::Messaging::Duration::SECOND.duration_impl). - and_return(@receiver_impl) - - receiver = @session.next_receiver Qpid::Messaging::Duration::SECOND - - receiver.receiver_impl.should == @receiver_impl - end - - it "returns nil when no Receiver has messages within the timeout period" do - @session_impl.should_receive(:nextReceiver). - with(Qpid::Messaging::Duration::MINUTE.duration_impl). - and_return(nil) - - receiver = @session.next_receiver Qpid::Messaging::Duration::MINUTE - - receiver.should be_nil - end - - it "returns true when there are errors on the session" do - @session_impl.should_receive(:hasError). - and_return(true) - - errors = @session.errors? - - errors.should be_true - end - - it "returns false when there are no errors on the session" do - @session_impl.should_receive(:hasError). - and_return(false) - - errors = @session.errors? - - errors.should be_false - end - - it "causes exceptions to be raised when there are errors" do - @session_impl.should_receive(:checkError). - and_raise(RuntimeError) - - expect { - @session.errors - }.to raise_error(RuntimeError) - end - - end - - end - -end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/address_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/address_spec.rb new file mode 100644 index 0000000000..05c97ddf30 --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/address_spec.rb @@ -0,0 +1,87 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Address do + + before(:each) do + @address = Qpid::Messaging::Address.new "my-name/my-subject;{create:always}" + end + + it "stores the name, subject and options when created" do + name = @address.name + subject = @address.subject + create = @address.options["create"] + + name.should == "my-name" + subject.should == "my-subject" + create.should == "always" + end + + it "can update the name" do + @address.name = "new-name" + + name = @address.name + + name.should == "new-name" + end + + it "can update the subject" do + @address.subject = "new-subject" + + subject = @address.subject + + subject.should == "new-subject" + end + + it "can update the type" do + @address.address_type = "routed" + + type = @address.address_type + + type.should == "routed" + end + + it "can update the options" do + @address.options[:create] = :never + + create = @address.options["create"] + + create.should == "always" + end + + it "can return a string representation" do + address = Qpid::Messaging::Address.new "foo/bar:{create:always,link:durable}" + result = address.to_s + + result.should =~ /foo\/bar/ + result.should =~ /create:always/ + result.should =~ /link:durable/ + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/connection_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/connection_spec.rb new file mode 100644 index 0000000000..811abf36e9 --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/connection_spec.rb @@ -0,0 +1,191 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Connection do + + before(:each) do + @session_impl = double('Cqpid::Session') + @connection_impl = double('Cqpid::Connection') + + @connection = Qpid::Messaging::Connection.new :impl => @connection_impl + end + + it "accepts options on construction" do + expect { + connection = Qpid::Messaging::Connection.new :options => {:username => "foo"} + + connection.options.should include("username") + }.to_not raise_error + end + + it "returns the underlying implementation" do + impl = @connection.connection_impl + + impl.should == @connection_impl + end + + it "opens the connection" do + @connection_impl.should_receive(:open) + + @connection.open + end + + it "closes the connection" do + @connection_impl.should_receive(:close) + + @connection.close + end + + it "retrieves a session by name" do + @connection_impl.should_receive(:getSession). + with("farkle"). + and_return(@session_impl) + + session = @connection.session "farkle" + + session.session_impl.should == @session_impl + end + + it "raises an error when a session name is invalid" do + @connection_impl.should_receive(:getSession). + with("farkle"). + and_raise(RuntimeError) + + expect { + @connection.session "farkle" + }.to raise_error(SessionNameException) + end + + #################################################################### + # test conditions for when a connection is not connected to a broker + #################################################################### + describe "when closed" do + + before(:each) do + @connection_impl.should_receive(:isOpen). + and_return(false) + end + + it "returns false when not connected to a broker" do + open = @connection.open? + + open.should == false + end + + it "should raise an error when creating a session on a closed connection" do + expect { + @connection.create_session + }.to raise_error(RuntimeError) + end + + it "raises an error when creating a transactional session on a closed connection" do + expect { + @connection.create_session :transactional => true + }.to raise_error(RuntimeError) + end + + it "raises an error when creating a named session on a closed connection" do + expect { + @connection.create_session :name => "test", :transactional => true + }.to raise_error(RuntimeError) + end + + it "returns a null username when not connected" do + username = @connection.authenticated_username + + username.should be_nil + end + + end + + ######################################################### + # test conditions for when a connection must be connected + ######################################################### + describe "when connected" do + + before(:each) do + @connection_impl.should_receive(:isOpen). + and_return(true) + end + + it "returns true when connected to a broker" do + open = @connection.open? + + open.should == true + end + + it "creates a session" do + @connection_impl.should_receive(:createSession). + and_return(@session_impl) + + session = @connection.create_session + + session.session_impl.should == @session_impl + end + + it "creates a named session with a name when provided" do + @connection_impl.should_receive(:createSession).with("farkle"). + and_return(@session_impl) + + session = @connection.create_session :name => "farkle" + + session.session_impl.should == @session_impl + end + + it "creates a transactional session when specified" do + @connection_impl.should_receive(:createTransactionalSession). + and_return(@session_impl) + + session = @connection.create_session :transactional => true + + session.session_impl.should == @session_impl + end + + it "creates a named transactional session when specified" do + @connection_impl.should_receive(:createTransactionalSession). + with("farkle"). + and_return(@session_impl) + + session = @connection.create_session :transactional => true, :name => "farkle" + + session.session_impl.should == @session_impl + end + + it "returns the authenticated username when connected" do + @connection_impl.should_receive(:getAuthenticatedUsername). + and_return("mcpierce") + + username = @connection.authenticated_username + + username.should == "mcpierce" + end + + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/duration_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/duration_spec.rb new file mode 100644 index 0000000000..202332d232 --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/duration_spec.rb @@ -0,0 +1,83 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Duration do + + before(:each) do + @duration = Qpid::Messaging::Duration::SECOND + end + + it "returns the underlying implementation" do + impl = @duration.duration_impl + + impl.should_not be_nil + end + + it "can create a duration with a millisecond value" do + duration = Qpid::Messaging::Duration.new 500 + + milliseconds = duration.milliseconds + + milliseconds.should == 500 + end + + it "returns the time in milliseconds" do + milliseconds = @duration.milliseconds + + milliseconds.should == 1000 + end + + it "raises an error when multiplied by a negative" do + expect { + twomin = Qpid::Messaging::Duration::MINUTE * -2 + }.to raise_error + end + + it "returns IMMEDIATE if the factor is zero" do + result = Qpid::Messaging::Duration::MINUTE * 0 + result.should be(Qpid::Messaging::Duration::IMMEDIATE) + end + + it "fractional factors return a reduced duration" do + factor = rand(1) + first = Qpid::Messaging::Duration::MINUTE + second = first * factor + + second.milliseconds.should == ((first.milliseconds * factor).floor) + end + + it "can return a multiple of its duration" do + factor = rand(10).floor + first = Qpid::Messaging::Duration.new(rand(10).floor * 10000) + second = first * factor + + second.milliseconds.should == first.milliseconds * factor + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/encoding_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/encoding_spec.rb new file mode 100644 index 0000000000..58b8447278 --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/encoding_spec.rb @@ -0,0 +1,63 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe "encoding" do + end + + describe "decoding" do + + before(:each) do + @message = Qpid::Messaging::Message.new + end + + it "can decode a message's text content" do + @message.content = "This is an unencoded message." + + content = Qpid::Messaging.decode @message + + content.should == "This is an unencoded message." + end + + it "can decode a message's list content" do + @message.content = ["this", "that"] + + content = Qpid::Messaging.decode @message + + content.should == ["this", "that"] + end + + it "can decode a message's map content" do + @message.content = {"this" => "that"} + + content = Qpid::Messaging.decode @message + + content.should == {"this" => "that"} + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/message_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/message_spec.rb new file mode 100644 index 0000000000..be19b3591e --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/message_spec.rb @@ -0,0 +1,305 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Message do + + before(:each) do + @message = Qpid::Messaging::Message.new :content => "My content" + end + + it "returns its implementation" do + impl = @message.message_impl + + impl.class.should == Cqpid::Message + end + + it "can set the reply to address" do + address = Qpid::Messaging::Address.new "my-queue;{create:always}" + + @message.reply_to = address + + reply_to = @message.reply_to + + reply_to.name.should == address.name + end + + it "can set the reply to from an address string" do + name = "my-queue" + subject = "responses" + address = "#{name}/#{subject}" + + @message.reply_to = address + + reply_to = @message.reply_to + + reply_to.name.should == name + reply_to.subject.should == subject + end + + it "should store the content when created" do + content = @message.content + + content.should == "My content" + end + + it "should properly encode a map when created" do + message = Qpid::Messaging::Message.new :content => {"foo" => "bar"} + + content = message.content + content_type = message.content_type + + content_type.should == "amqp/map" + content.class == Hash + content["foo"].should == "bar" + end + + it "should properly encode a list when created" do + message = Qpid::Messaging::Message.new :content => ["foo", "bar"] + + content = message.content + content_type = message.content_type + + content_type.should == "amqp/list" + content.class == Array + content.should include("foo") + content.should include("bar") + end + + it "should store the subject" do + @message.subject = "new-subject" + + subject = @message.subject + + subject.should == "new-subject" + end + + it "should update the content type" do + @message.content_type = "amqp/audio" + + content_type = @message.content_type + + content_type.should == "amqp/audio" + end + + it "should store the message id" do + @message.message_id = "foo" + + id = @message.message_id + + id.should == "foo" + end + + it "should store the user id" do + @message.user_id = "foo" + + id = @message.user_id + + id.should == "foo" + end + + it "should store the correlation id" do + @message.correlation_id = "message1" + + id = @message.correlation_id + + id.should == "message1" + end + + it "should store the priority" do + @message.priority = 7 + + priority = @message.priority + + priority.should == 7 + end + + it "should accept a Duration as the time to live" do + @message.ttl = Qpid::Messaging::Duration::SECOND + + ttl = @message.ttl + + ttl.milliseconds.should == Qpid::Messaging::Duration::SECOND.milliseconds + end + + it "should accept an integer value as the time to live" do + @message.ttl = 15000 + + ttl = @message.ttl + + ttl.milliseconds.should == 15000 + end + + it "should update the durable flag" do + @message.durable = true + + durable = @message.durable + + durable.should == true + end + + it "should update the redelivered flag" do + @message.redelivered = true + + redelivered = @message.redelivered + + redelivered.should == true + end + + it "should store a property" do + property = @message[:test_property] + + property.should == nil + + @message[:test_property] = "test_value1" + + property = @message[:test_property] + + property.should == "test_value1" + end + + it "should convert a symbol property value to a string" do + @message[:test_property] = :test_value2 + + property = @message[:test_property] + + property.should == "test_value2" + end + + it "should convert a symbol property name to a string" do + @message[:test_property] = "test_value3" + + property = @message["test_property"] + + property.should == "test_value3" + end + + it "should store text content" do + @message.content = "This is the content." + + content = @message.content + + content.should == "This is the content." + end + + it "should store list content" do + list = ["foo", "bar"] + + @message.content = list + + content = @message.content + content_type = @message.content_type + + content.should == list + content_type.should == "amqp/list" + end + + it "should convert symbol list elements to strings" do + @message.content = [:farkle] + + content = @message.content.first + + content.should == "farkle" + end + + it "should store map content" do + map = {"foo" => "bar"} + + @message.content = map + + content = @message.content + content_type = @message.content_type + + content.should == map + content_type.should == "amqp/map" + end + + it "should convert symbol map elements to strings" do + @message.content = {:first_name => :qpid} + + content = @message.content["first_name"] + + content.should == "qpid" + end + + describe "with content from the underlying implementation" do + + before(:each) do + @message_impl = double("Cqpid::Message") + @message = Qpid::Messaging::Message.new :impl => @message_impl + end + + it "should return simple text content" do + @message_impl.should_receive(:getContent). + and_return("my content") + @message_impl.should_receive(:getContentType). + and_return("") + + content = @message.content + + content.should == "my content" + end + + it "should decode a list" do + list = ["first", "second"] + + @message_impl.should_receive(:getContent). + and_return(list) + @message_impl.should_receive(:getContentType). + twice. + and_return("amqp/list") + Qpid::Messaging.stub!(:decode). + with(@message, "amqp/list"). + and_return(list) + + content = @message.content + + content.should == list + end + + it "should decode a map" do + map = {"first" => "second"} + + @message_impl.should_receive(:getContent). + and_return(map) + @message_impl.should_receive(:getContentType). + twice. + and_return("amqp/map") + Qpid::Messaging.stub!(:decode). + with(@message, "amqp/map"). + and_return(map) + + content = @message.content + + content.should == map + end + + + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/receiver_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/receiver_spec.rb new file mode 100644 index 0000000000..81ae935dcb --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/receiver_spec.rb @@ -0,0 +1,170 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Receiver do + + before(:each) do + @message_impl = double("Cqpid::Message") + @session = double("Qpid::Messaging::Session") + @receiver_impl = double("Cqpid::Receiver") + + @receiver = Qpid::Messaging::Receiver.new @session, @receiver_impl + end + + it "returns the underlying implementation" do + impl = @receiver.receiver_impl + + impl.should == @receiver_impl + end + + it "gets a message with the default duration" do + @receiver_impl.should_receive(:get). + with(Qpid::Messaging::Duration::FOREVER.duration_impl). + and_return(@message_impl) + + message = @receiver.get + + message.message_impl.should == @message_impl + end + + it "gets a message with a specified duration" do + @receiver_impl.should_receive(:get). + with(Qpid::Messaging::Duration::SECOND.duration_impl). + and_return(@message_impl) + + message = @receiver.get Qpid::Messaging::Duration::SECOND + + message.message_impl.should == @message_impl + end + + it "returns nil when get receives no message" do + @receiver_impl.should_receive(:get). + with(Qpid::Messaging::Duration::MINUTE.duration_impl). + and_return(nil) + + message = @receiver.get Qpid::Messaging::Duration::MINUTE + + message.should be_nil + end + + it "fetches a message with the default duration" do + @receiver_impl.should_receive(:fetch). + with(Qpid::Messaging::Duration::FOREVER.duration_impl). + and_return(@message_impl) + + message = @receiver.fetch + + message.message_impl.should == @message_impl + end + + it "fetches a message with a specified duration" do + @receiver_impl.should_receive(:fetch). + with(Qpid::Messaging::Duration::SECOND.duration_impl). + and_return(@message_impl) + + message = @receiver.fetch Qpid::Messaging::Duration::SECOND + + message.message_impl.should == @message_impl + end + + it "returns nil when fetch recieves no message" do + @receiver_impl.should_receive(:fetch). + with(Qpid::Messaging::Duration::MINUTE.duration_impl). + and_return(nil) + + message = @receiver.fetch Qpid::Messaging::Duration::MINUTE + + message.should be_nil + end + + it "assigns capacity" do + @receiver_impl.should_receive(:setCapacity). + with(10) + + @receiver.capacity = 10 + end + + it "returns the capacity" do + @receiver_impl.should_receive(:getCapacity). + and_return(10) + + capacity = @receiver.capacity + + capacity.should == 10 + end + + it "reports the number of available messages" do + @receiver_impl.should_receive(:getAvailable). + and_return(20) + + available = @receiver.available + + available.should == 20 + end + + it "reports the number of unsettled messages" do + @receiver_impl.should_receive(:getUnsettled). + and_return(25) + + unsettled = @receiver.unsettled + + unsettled.should == 25 + end + + it "closes" do + @receiver_impl.should_receive(:close) + + @receiver.close + end + + it "reports its closed status" do + @receiver_impl.should_receive(:isClosed). + and_return(true) + + closed = @receiver.closed? + + closed.should == true + end + + it "returns its name" do + @receiver_impl.should_receive(:getName). + and_return("farkle") + + name = @receiver.name + + name.should == "farkle" + end + + it "returns its related session" do + session = @receiver.session + + session.should == @session + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/sender_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/sender_spec.rb new file mode 100644 index 0000000000..fa3a2a5b1f --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/sender_spec.rb @@ -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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Sender do + + before(:each) do + @message = double("Qpid::Messaging::Message") + @message_impl = double("Cqpid::Message") + @sender_impl = double("Cqpid::Sender") + @session = double("Qpid::Messaging::Session") + + @sender = Qpid::Messaging::Sender.new @session, @sender_impl + end + + it "returns its implementation" do + impl = @sender.sender_impl + + impl.should == @sender_impl + end + + it "sends a message" do + @message.should_receive(:message_impl). + and_return(@message_impl) + @sender_impl.should_receive(:send). + with(@message_impl, false) + + @sender.send @message + end + + it "sends a message with optional synch" do + @message.should_receive(:message_impl). + and_return(@message_impl) + @sender_impl.should_receive(:send). + with(@message_impl, true) + + @sender.send @message, :sync => true + end + + it "sends a message with an optional block" do + block_called = false + + @message.should_receive(:message_impl). + and_return(@message_impl) + @sender_impl.should_receive(:send). + with(@message_impl, false) + + @sender.send @message do |message| + block_called = true if message == @message + end + + block_called.should be_true + end + + it "closes" do + @sender_impl.should_receive(:close) + + @sender.close + end + + it "returns its name" do + @sender_impl.should_receive(:getName). + and_return("farkle") + + name = @sender.name + + name.should == "farkle" + end + + it "sets its capacity" do + @sender_impl.should_receive(:setCapacity). + with(100) + + @sender.capacity = 100 + end + + it "returns its capacity" do + @sender_impl.should_receive(:getCapacity). + and_return(25) + + capacity = @sender.capacity + + capacity.should == 25 + end + + it "returns the number of unsettled messages" do + @sender_impl.should_receive(:getUnsettled). + and_return(15) + + unsettled = @sender.unsettled + + unsettled.should == 15 + end + + it "returns the number of available message slots" do + @sender_impl.should_receive(:getAvailable). + and_return(50) + + available = @sender.available + + available.should == 50 + end + + it "returns a reference to its session" do + session = @sender.session + + session.should == @session + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/qpid_messaging/session_spec.rb b/cpp/bindings/qpid/ruby/spec/qpid_messaging/session_spec.rb new file mode 100644 index 0000000000..754e2ca88f --- /dev/null +++ b/cpp/bindings/qpid/ruby/spec/qpid_messaging/session_spec.rb @@ -0,0 +1,353 @@ +# +# 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. +# + +require 'spec_helper' + +module Qpid + + module Messaging + + describe Session do + + before(:each) do + @connection = double("Qpid::Messaging::Connection") + @session_impl = double("Cqpid::Session") + @session = Qpid::Messaging::Session.new @connection, @session_impl + @sender_impl = double("Cqpid::Sender") + @receiver_impl = double("Cqpid::Receiver") + end + + it "returns its implementation" do + impl = @session.session_impl + + impl.should == @session_impl + end + + it "returns its connection" do + connection = @session.connection + + connection.should == @connection + end + + it "creates a Sender from an Address" do + address = Qpid::Messaging::Address.new "my-queue;{create:always}" + + @session_impl.should_receive(:createSender). + with(address.address_impl). + and_return(@sender_impl) + @sender_impl.should_receive(:getName). + and_return("my-queue") + + sender = @session.create_sender address + + sender.sender_impl.should == @sender_impl + end + + it "creates a Sender from an address string" do + address = "my-queue;{create:true}" + + @session_impl.should_receive(:createSender). + with(address). + and_return(@sender_impl) + @sender_impl.should_receive(:getName). + and_return("my-queue") + + sender = @session.create_sender address + + sender.sender_impl.should == @sender_impl + end + + ####################################### + # scenarios involing an existing Sender + ####################################### + describe "when retrieving a Sender by name" do + + before(:each) do + address = "my-queue;{create:always}" + @name = "my-queue" + + @session_impl.should_receive(:createSender). + with(address). + and_return(@sender_impl) + @sender_impl.should_receive(:getName). + and_return(@name) + + @sender = @session.create_sender address + end + + it "works when the name is valid" do + sender = @session.sender @name + + sender.should == @sender + end + + it "raises an error when the name is invalid" do + expect { + @session.sender @name.reverse + }.to raise_error(Qpid::Messaging::KeyError) + end + + end + + it "creates a Receiver from an Address" do + address = Qpid::Messaging::Address.new "my-queue", "" + + @session_impl.should_receive(:createReceiver). + with(address.address_impl). + and_return(@receiver_impl) + @receiver_impl.should_receive(:getName). + and_return("my-queue") + + receiver = @session.create_receiver address + + receiver.receiver_impl.should == @receiver_impl + end + + it "creates a Receiver from an address string" do + address = "my-queue" + + @session_impl.should_receive(:createReceiver). + with(address). + and_return(@receiver_impl) + @receiver_impl.should_receive(:getName). + and_return("my-queue") + + receiver = @session.create_receiver address + + receiver.receiver_impl.should == @receiver_impl + end + + ######################################### + # scenarios involving an existing Receiver + ########################################## + describe "when retrieving a Receiver by name" do + + before(:each) do + address = "my-queue" + @name = "my-queue" + + @session_impl.should_receive(:createReceiver). + with(address). + and_return(@receiver_impl) + @receiver_impl.should_receive(:getName). + and_return(@name) + + @receiver = @session.create_receiver address + end + + it "works with a valid name" do + receiver = @session.receiver @name + + receiver.should == @receiver + end + + it "raises an error when the name is invalid" do + expect { + @session.receiver @name.reverse + }.to raise_error(Qpid::Messaging::KeyError) + end + + end + + it "closes the session" do + @session_impl.should_receive(:close) + + @session.close + end + + it "commits a pending transaction" do + @session_impl.should_receive(:commit) + + @session.commit + end + + it "rolls back an uncommitted transaction" do + @session_impl.should_receive(:rollback) + + @session.rollback + end + + it "acknowledges all received messages" do + @session_impl.should_receive(:acknowledge). + with(false) + + @session.acknowledge + end + + it "acknowledges all messages synchronously" do + @session_impl.should_receive(:acknowledge). + with(true) + + @session.acknowledge :sync => true + end + + it "acknowledges all messages asynchronously" do + @session_impl.should_receive(:acknowledge). + with(false) + + @session.acknowledge :sync => false + end + + ###################################### + # Scenarios involving a single message + ###################################### + describe "with a single message" do + + before(:each) do + @message = Qpid::Messaging::Message.new :content => "Testing" + end + + it "can acknowledge asynchronously by default" do + @session_impl.should_receive(:acknowledge). + with(@message.message_impl, false) + + @session.acknowledge :message => @message + end + + it "can acknowledge synchronously" do + @session_impl.should_receive(:acknowledge). + with(@message.message_impl, true) + + @session.acknowledge :message => @message, :sync => true + end + + it "can acknowledge asynchronously" do + @session_impl.should_receive(:acknowledge). + with(@message.message_impl, false) + + @session.acknowledge :message => @message, :sync => false + end + + it "can reject it" do + @session_impl.should_receive(:reject). + with(@message.message_impl) + + @session.reject @message + end + + it "can release it" do + @session_impl.should_receive(:release). + with(@message.message_impl) + + @session.release @message + end + + end + + it "does not block by default when synchronizating with the broker" do + @session_impl.should_receive(:sync). + with(false) + + @session.sync + end + + it "can block while synchronizing with the broker" do + @session_impl.should_receive(:sync). + with(true) + + @session.sync :block => true + end + + it "can not block while synchronizing with the broker" do + @session_impl.should_receive(:sync). + with(false) + + @session.sync :block => false + end + + it "returns the number of messages that are receivable" do + @session_impl.should_receive(:getReceivable). + and_return(15) + + receivable = @session.receivable + + receivable.should == 15 + end + + it "returns the number of unsettled messages" do + @session_impl.should_receive(:getUnsettledAcks). + and_return(25) + + unsettled = @session.unsettled_acks + + unsettled.should == 25 + end + + it "waits forever by default for the next Receiver with messages" do + @session_impl.should_receive(:nextReceiver). + with(Qpid::Messaging::Duration::FOREVER.duration_impl). + and_return(@receiver_impl) + + receiver = @session.next_receiver + + receiver.receiver_impl.should == @receiver_impl + end + + it "uses the specified time when waiting for the next Receiver with messages" do + @session_impl.should_receive(:nextReceiver). + with(Qpid::Messaging::Duration::SECOND.duration_impl). + and_return(@receiver_impl) + + receiver = @session.next_receiver Qpid::Messaging::Duration::SECOND + + receiver.receiver_impl.should == @receiver_impl + end + + it "returns nil when no Receiver has messages within the timeout period" do + @session_impl.should_receive(:nextReceiver). + with(Qpid::Messaging::Duration::MINUTE.duration_impl). + and_return(nil) + + receiver = @session.next_receiver Qpid::Messaging::Duration::MINUTE + + receiver.should be_nil + end + + it "returns true when there are errors on the session" do + @session_impl.should_receive(:hasError). + and_return(true) + + errors = @session.errors? + + errors.should be_true + end + + it "returns false when there are no errors on the session" do + @session_impl.should_receive(:hasError). + and_return(false) + + errors = @session.errors? + + errors.should be_false + end + + it "causes exceptions to be raised when there are errors" do + @session_impl.should_receive(:checkError). + and_raise(RuntimeError) + + expect { + @session.errors + }.to raise_error(RuntimeError) + end + + end + + end + +end diff --git a/cpp/bindings/qpid/ruby/spec/spec_helper.rb b/cpp/bindings/qpid/ruby/spec/spec_helper.rb index 90084963f4..865e60e0e2 100644 --- a/cpp/bindings/qpid/ruby/spec/spec_helper.rb +++ b/cpp/bindings/qpid/ruby/spec/spec_helper.rb @@ -17,5 +17,4 @@ # under the License. # -require 'qpid' -require 'cqpid' +require 'qpid_messaging' diff --git a/cpp/bindings/swig_perl_typemaps.i b/cpp/bindings/swig_perl_typemaps.i deleted file mode 100644 index 831576a7d4..0000000000 --- a/cpp/bindings/swig_perl_typemaps.i +++ /dev/null @@ -1,330 +0,0 @@ -/* - * 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. - */ - -%wrapper %{ - -#include - - SV* MapToPerl(const qpid::types::Variant::Map*); - SV* ListToPerl(const qpid::types::Variant::List*); - void PerlToMap(SV*, qpid::types::Variant::Map*); - void PerlToList(SV*, qpid::types::Variant::List*); - - qpid::types::Variant PerlToVariant(SV* value) { - if (SvROK(value)) { - if (SvTYPE(SvRV(value)) == SVt_PVHV) { - qpid::types::Variant::Map map; - PerlToMap(value, &map); - return qpid::types::Variant(map); - } - else if (SvTYPE(SvRV(value)) == SVt_PVAV) { - qpid::types::Variant::List list; - PerlToList(value, &list); - return qpid::types::Variant(list); - } - } - else { - if (SvIOK(value)) { - return qpid::types::Variant((int64_t) SvIV(value)); - } - else if (SvNOK(value)) { - return qpid::types::Variant((float)SvNV(value)); - } - else if (SvPOK(value)) { - return qpid::types::Variant(std::string(SvPV_nolen(value))); - } - } - return qpid::types::Variant(); - } - - SV* VariantToPerl(const qpid::types::Variant* v) { - SV* result = newSV(0); - try { - switch (v->getType()) { - case qpid::types::VAR_VOID: { - sv_setiv(result, (IV)0); - break; - } - case qpid::types::VAR_BOOL : { - result = boolSV(v->asBool()); - break; - } - case qpid::types::VAR_UINT8 : - case qpid::types::VAR_UINT16 : - case qpid::types::VAR_UINT32 : { - sv_setuv(result, (UV)v->asUint32()); - break; - } - case qpid::types::VAR_UINT64 : { - sv_setuv(result, (UV)v->asUint64()); - break; - } - case qpid::types::VAR_INT8 : - case qpid::types::VAR_INT16 : - case qpid::types::VAR_INT32 : { - sv_setiv(result, (IV)v->asInt32()); - break; - } - case qpid::types::VAR_INT64 : { - sv_setiv(result, (IV)v->asInt64()); - break; - } - case qpid::types::VAR_FLOAT : { - sv_setnv(result, (double)v->asFloat()); - break; - } - case qpid::types::VAR_DOUBLE : { - sv_setnv(result, (double)v->asDouble()); - break; - } - case qpid::types::VAR_STRING : { - const std::string val(v->asString()); - result = newSVpvn(val.c_str(), val.size()); - break; - } - case qpid::types::VAR_MAP : { - result = MapToPerl(&(v->asMap())); - break; - } - case qpid::types::VAR_LIST : { - result = ListToPerl(&(v->asList())); - break; - } - case qpid::types::VAR_UUID : { - } - } - } catch (qpid::types::Exception& ex) { - Perl_croak(aTHX_ ex.what()); - } - - return result; - } - - SV* MapToPerl(const qpid::types::Variant::Map* map) { - SV *result = newSV(0); - HV *hv = (HV *)sv_2mortal((SV *)newHV()); - qpid::types::Variant::Map::const_iterator iter; - for (iter = map->begin(); iter != map->end(); iter++) { - const std::string key(iter->first); - SV* perlval = VariantToPerl(&(iter->second)); - hv_store(hv, key.c_str(), key.size(), perlval, 0); - } - SvSetSV(result, newRV_noinc((SV *)hv)); - return result; - } - - SV* ListToPerl(const qpid::types::Variant::List* list) { - SV* result = newSV(0); - AV* av = (AV *)sv_2mortal((SV *)newAV()); - qpid::types::Variant::List::const_iterator iter; - for (iter = list->begin(); iter != list->end(); iter++) { - SV* perlval = VariantToPerl(&(*iter)); - av_push(av, perlval); - } - SvSetSV(result, newRV_noinc((SV *)av)); - return result; - } - - void PerlToMap(SV* hash, qpid::types::Variant::Map* map) { - map->clear(); - HV* hv = (HV *)SvRV(hash); - HE* he; - while((he = hv_iternext(hv)) != NULL) { - SV* svkey = HeSVKEY_force(he); - SV* svval = HeVAL(he); - (*map)[std::string(SvPV_nolen(svkey))] = PerlToVariant(svval); - } - } - - void PerlToList(SV* ary, qpid::types::Variant::List* list) { - list->clear(); - AV * av = (AV *)SvRV(ary); - I32 len = av_len(av) + 1; - if (len > 0) { - for (I32 i = 0; i < len; i++) { - list->push_back(PerlToVariant(*av_fetch(av, i, 0))); - } - } - } -%} - -%typemap (in) void * { - $1 = (void *)SvIV($input); -} - -%typemap (out) void * { - sv_setiv($result, (IV)$1); - argvi++; -} - -%typemap (in) uint16_t, uint32_t, uint64_t { - if (SvIOK($input)) { - $1 = ($1_ltype)SvUV($input); - } - else { - SWIG_exception_fail(SWIG_ValueError, "not an integer"); - } -} - -%typemap (out) uint16_t, uint32_t, uint64_t { - sv_setuv($result, (UV)$1); - argvi++; -} - -%typemap (in) int32_t, int64_t { - if (SvIOK($input)) { - $1 = ($1_ltype)SvIV($input); - } - else { - SWIG_exception_fail(SWIG_ValueError, "not an integer"); - } -} - -%typemap (out) int32_t, int64_t { - sv_setiv($result, (IV)$1); - argvi++; -} - -%typemap(in) bool { - $1 = (bool)SvTRUE($input); -} - -%typemap (out) bool { - $result = boolSV($1); - argvi++; -} - - -%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT64) uint64_t { - $1 = SvIOK($input) ? 1 : 0; -} - -%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT32) uint32_t { - $1 = SvIOK($input) ? 1 : 0; -} - - -/* - * Variant types: C++ --> Perl - */ -%typemap(out) qpid::types::Variant::Map { - $result = MapToPerl(&$1); - argvi++; -} - -%typemap(out) qpid::types::Variant::Map& { - $result = MapToPerl($1); - argvi++; -} - -%typemap(out) qpid::types::Variant::List { - $result = ListToPerl(&$1); - argvi++; -} - -%typemap(out) qpid::types::Variant::List& { - $result = ListToPerl($1); - argvi++; -} - -%typemap(out) qpid::types::Variant& { - $result = VariantToPerl($1); - argvi++; -} - - -/* - * Variant types: Perl --> C++ - */ -%typemap(in) qpid::types::Variant& { - $1 = new qpid::types::Variant(PerlToVariant($input)); -} - -%typemap(in) qpid::types::Variant::Map& { - $1 = new qpid::types::Variant::Map(); - PerlToMap($input, $1); - -} - -%typemap(in) qpid::types::Variant::List& { - $1 = new qpid::types::Variant::List(); - PerlToList($input, $1); - -} - -%typemap(in) const qpid::types::Variant::Map const & { - $1 = new qpid::types::Variant::Map(); - PerlToMap($input, $1); -} - -%typemap(in) const qpid::types::Variant::List const & { - $1 = new qpid::types::Variant::List(); - PerlToList($input, $1); -} - -%typemap(freearg) qpid::types::Variant& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::Map& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::List& { - delete $1; -} - - -/* - * Variant types: typecheck maps - */ -%typemap(typecheck) qpid::types::Variant::Map& { - $1 = (SvTYPE(SvRV($input)) == SVt_PVHV) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant::List& { - $1 = (SvTYPE(SvRV($input)) == SVt_PVAV) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant& { - $1 = (SvIOK($input) || - SvNOK($input) || - SvPOK($input) ) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant::Map const & { - $1 = (SvTYPE(SvRV($input)) == SVt_PVHV) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant::List const & { - $1 = (SvTYPE(SvRV($input)) == SVt_PVAV) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant const & { - $1 = (SvIOK($input) || - SvNOK($input) || - SvPOK($input) ) ? 1 : 0; -} - -/* No boolean type for perl. - Boolean is simply and integer in perl -*/ -%typecheck(SWIG_TYPECHECK_BOOL) bool { - $1 = (SvIOK($input)) ? 1 : 0; -} diff --git a/cpp/bindings/swig_python_typemaps.i b/cpp/bindings/swig_python_typemaps.i deleted file mode 100644 index 25a4e46b18..0000000000 --- a/cpp/bindings/swig_python_typemaps.i +++ /dev/null @@ -1,446 +0,0 @@ -/* - * 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 UUID objects, to convert them to Python uuid.UUID objects, - * we'll need a reference to the uuid module. - */ -%{ -static PyObject* pUuidModule; -%} - -%init %{ - /* Instead of directly referencing the uuid module (which is not available - * on older versions of Python), reference the wrapper defined in - * qpid.datatypes. - */ - pUuidModule = PyImport_ImportModule("qpid.datatypes"); - - /* Although it is not required, we'll publish the uuid module in our - * module, as if this module was a python module and we called - * "import uuid" - */ - Py_INCREF(pUuidModule); - PyModule_AddObject(m, "uuid", pUuidModule); -%} - - -%wrapper %{ - -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#endif - - - PyObject* MapToPy(const qpid::types::Variant::Map*); - PyObject* ListToPy(const qpid::types::Variant::List*); - PyObject* UuidToPy(const qpid::types::Uuid*); - void PyToMap(PyObject*, qpid::types::Variant::Map*); - void PyToList(PyObject*, qpid::types::Variant::List*); - - qpid::types::Variant PyToVariant(PyObject* value) { - if (PyBool_Check(value)) return qpid::types::Variant(bool(PyInt_AS_LONG(value) ? true : false)); - if (PyFloat_Check(value)) return qpid::types::Variant(PyFloat_AS_DOUBLE(value)); - if (PyInt_Check(value)) return qpid::types::Variant(int64_t(PyInt_AS_LONG(value))); - if (PyLong_Check(value)) return qpid::types::Variant(int64_t(PyLong_AsLongLong(value))); - if (PyString_Check(value)) return qpid::types::Variant(std::string(PyString_AS_STRING(value))); - if (PyDict_Check(value)) { - qpid::types::Variant::Map map; - PyToMap(value, &map); - return qpid::types::Variant(map); - } - if (PyList_Check(value)) { - qpid::types::Variant::List list; - PyToList(value, &list); - return qpid::types::Variant(list); - } - return qpid::types::Variant(); - } - - PyObject* VariantToPy(const qpid::types::Variant* v) { - PyObject* result; - try { - switch (v->getType()) { - case qpid::types::VAR_VOID: { - result = Py_None; - break; - } - case qpid::types::VAR_BOOL : { - result = v->asBool() ? Py_True : Py_False; - break; - } - case qpid::types::VAR_UINT8 : - case qpid::types::VAR_UINT16 : - case qpid::types::VAR_UINT32 : { - result = PyInt_FromLong((long) v->asUint32()); - break; - } - case qpid::types::VAR_UINT64 : { - result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) v->asUint64()); - break; - } - case qpid::types::VAR_INT8 : - case qpid::types::VAR_INT16 : - case qpid::types::VAR_INT32 : { - result = PyInt_FromLong((long) v->asInt32()); - break; - } - case qpid::types::VAR_INT64 : { - result = PyLong_FromLongLong((PY_LONG_LONG) v->asInt64()); - break; - } - case qpid::types::VAR_FLOAT : { - result = PyFloat_FromDouble((double) v->asFloat()); - break; - } - case qpid::types::VAR_DOUBLE : { - result = PyFloat_FromDouble((double) v->asDouble()); - break; - } - case qpid::types::VAR_STRING : { - const std::string val(v->asString()); - result = PyString_FromStringAndSize(val.c_str(), val.size()); - break; - } - case qpid::types::VAR_MAP : { - result = MapToPy(&(v->asMap())); - break; - } - case qpid::types::VAR_LIST : { - result = ListToPy(&(v->asList())); - break; - } - case qpid::types::VAR_UUID : { - qpid::types::Uuid uuid = v->asUuid(); - result = UuidToPy(&uuid); - break; - } - } - } catch (qpid::types::Exception& ex) { - PyErr_SetString(PyExc_RuntimeError, ex.what()); - result = 0; - } - - return result; - } - - PyObject* MapToPy(const qpid::types::Variant::Map* map) { - PyObject* result = PyDict_New(); - qpid::types::Variant::Map::const_iterator iter; - for (iter = map->begin(); iter != map->end(); iter++) { - const std::string key(iter->first); - PyObject* pyval = VariantToPy(&(iter->second)); - if (pyval == 0) - return 0; - PyDict_SetItem(result, PyString_FromStringAndSize(key.c_str(), key.size()), pyval); - } - return result; - } - - PyObject* ListToPy(const qpid::types::Variant::List* list) { - PyObject* result = PyList_New(list->size()); - qpid::types::Variant::List::const_iterator iter; - Py_ssize_t idx(0); - for (iter = list->begin(); iter != list->end(); iter++) { - PyObject* pyval = VariantToPy(&(*iter)); - if (pyval == 0) - return 0; - PyList_SetItem(result, idx, pyval); - idx++; - } - return result; - } - - PyObject* UuidToPy(const qpid::types::Uuid * uuid) { - PyObject* pUuidClass = PyObject_GetAttrString(pUuidModule, "UUID"); - if (!pUuidClass) { - // Failed to get UUID class - return 0; - } - - PyObject* pArgs = PyTuple_New(0); - PyObject* pKw = PyDict_New(); - PyObject* pData = PyString_FromStringAndSize( - (const char*)(uuid->data()), 16); - PyDict_SetItemString(pKw, "bytes", pData); - - PyObject* result = PyObject_Call(pUuidClass, pArgs, pKw); - - Py_DECREF(pData); - Py_DECREF(pKw); - Py_DECREF(pArgs); - Py_DECREF(pUuidClass); - - return result; - } - - - void PyToMap(PyObject* obj, qpid::types::Variant::Map* map) { - map->clear(); - Py_ssize_t iter(0); - PyObject *key; - PyObject *val; - while (PyDict_Next(obj, &iter, &key, &val)) - (*map)[std::string(PyString_AS_STRING(key))] = PyToVariant(val); - } - - void PyToList(PyObject* obj, qpid::types::Variant::List* list) { - list->clear(); - Py_ssize_t count(PyList_Size(obj)); - for (Py_ssize_t idx = 0; idx < count; idx++) - list->push_back(PyToVariant(PyList_GetItem(obj, idx))); - } - -%} - - -/* unsigned32 Convert from Python --> C */ -%typemap(in) uint32_t { - if (PyInt_Check($input)) { - $1 = (uint32_t) PyInt_AsUnsignedLongMask($input); - } else if (PyLong_Check($input)) { - $1 = (uint32_t) PyLong_AsUnsignedLong($input); - } else { - SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); - } -} - -/* unsinged32 Convert from C --> Python */ -%typemap(out) uint32_t { - $result = PyInt_FromLong((long)$1); -} - - -/* unsigned16 Convert from Python --> C */ -%typemap(in) uint16_t { - if (PyInt_Check($input)) { - $1 = (uint16_t) PyInt_AsUnsignedLongMask($input); - } else if (PyLong_Check($input)) { - $1 = (uint16_t) PyLong_AsUnsignedLong($input); - } else { - SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); - } -} - -/* unsigned16 Convert from C --> Python */ -%typemap(out) uint16_t { - $result = PyInt_FromLong((long)$1); -} - - -/* signed32 Convert from Python --> C */ -%typemap(in) int32_t { - if (PyInt_Check($input)) { - $1 = (int32_t) PyInt_AsLong($input); - } else if (PyLong_Check($input)) { - $1 = (int32_t) PyLong_AsLong($input); - } else { - SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); - } -} - -/* signed32 Convert from C --> Python */ -%typemap(out) int32_t { - $result = PyInt_FromLong((long)$1); -} - - -/* unsigned64 Convert from Python --> C */ -%typemap(in) uint64_t { -%#ifdef HAVE_LONG_LONG - if (PyLong_Check($input)) { - $1 = (uint64_t)PyLong_AsUnsignedLongLong($input); - } else if (PyInt_Check($input)) { - $1 = (uint64_t)PyInt_AsUnsignedLongLongMask($input); - } else -%#endif - { - SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - uint64_t input too large"); - } -} - -/* unsigned64 Convert from C --> Python */ -%typemap(out) uint64_t { -%#ifdef HAVE_LONG_LONG - $result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)$1); -%#else - SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - uint64_t output too large"); -%#endif -} - -/* signed64 Convert from Python --> C */ -%typemap(in) int64_t { -%#ifdef HAVE_LONG_LONG - if (PyLong_Check($input)) { - $1 = (int64_t)PyLong_AsLongLong($input); - } else if (PyInt_Check($input)) { - $1 = (int64_t)PyInt_AsLong($input); - } else -%#endif - { - SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - int64_t input too large"); - } -} - -/* signed64 Convert from C --> Python */ -%typemap(out) int64_t { -%#ifdef HAVE_LONG_LONG - $result = PyLong_FromLongLong((PY_LONG_LONG)$1); -%#else - SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - int64_t output too large"); -%#endif -} - - -/* Convert from Python --> C */ -%typemap(in) void * { - $1 = (void *)$input; -} - -/* Convert from C --> Python */ -%typemap(out) void * { - $result = (PyObject *) $1; - Py_INCREF($result); -} - -/* - * Variant types: C++ --> Python - */ -%typemap(out) qpid::types::Variant::Map { - $result = MapToPy(&$1); -} - -%typemap(out) qpid::types::Variant::Map& { - $result = MapToPy($1); -} - -%typemap(out) qpid::types::Variant::List { - $result = ListToPy(&$1); -} - -%typemap(out) qpid::types::Variant::List& { - $result = ListToPy($1); -} - -%typemap(out) qpid::types::Variant& { - $result = VariantToPy($1); -} - -/* - * UUID type: C++ --> Python - */ -%typemap(out) qpid::types::UUID & { - $result = UuidToPy($1); -} - - -/* - * Variant types: Ruby --> C++ - */ -%typemap(in) qpid::types::Variant& { - $1 = new qpid::types::Variant(PyToVariant($input)); -} - -%typemap(in) qpid::types::Variant::Map& { - $1 = new qpid::types::Variant::Map(); - PyToMap($input, $1); -} - -%typemap(in) qpid::types::Variant::List& { - $1 = new qpid::types::Variant::List(); - PyToList($input, $1); -} - -%typemap(in) const qpid::types::Variant::Map const & { - $1 = new qpid::types::Variant::Map(); - PyToMap($input, $1); -} - -%typemap(in) const qpid::types::Variant::List const & { - $1 = new qpid::types::Variant::List(); - PyToList($input, $1); -} - -%typemap(freearg) qpid::types::Variant& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::Map& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::List& { - delete $1; -} - - -/* - * Variant types: typecheck maps - */ -%typemap(typecheck) qpid::types::Variant::Map& { - $1 = PyDict_Check($input) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant::List& { - $1 = PyList_Check($input) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant& { - $1 = (PyFloat_Check($input) || - PyString_Check($input) || - PyInt_Check($input) || - PyLong_Check($input) || - PyDict_Check($input) || - PyList_Check($input) || - PyBool_Check($input)) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant::Map const & { - $1 = PyDict_Check($input) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant::List const & { - $1 = PyList_Check($input) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant const & { - $1 = (PyFloat_Check($input) || - PyString_Check($input) || - PyInt_Check($input) || - PyLong_Check($input) || - PyDict_Check($input) || - PyList_Check($input) || - PyBool_Check($input)) ? 1 : 0; -} - -%typemap(typecheck) bool { - $1 = PyBool_Check($input) ? 1 : 0; -} - - - -%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT64) uint64_t { - $1 = PyLong_Check($input) ? 1 : 0; -} - -%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT32) uint32_t { - $1 = PyInt_Check($input) ? 1 : 0; -} - diff --git a/cpp/bindings/swig_ruby_typemaps.i b/cpp/bindings/swig_ruby_typemaps.i deleted file mode 100644 index 1a07cc86b0..0000000000 --- a/cpp/bindings/swig_ruby_typemaps.i +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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. - */ - -%wrapper %{ - -#include - - VALUE MapToRb(const qpid::types::Variant::Map*); - VALUE ListToRb(const qpid::types::Variant::List*); - void RbToMap(VALUE, qpid::types::Variant::Map*); - void RbToList(VALUE, qpid::types::Variant::List*); - - qpid::types::Variant RbToVariant(VALUE value) { - switch (TYPE(value)) { - case T_FLOAT: return qpid::types::Variant(NUM2DBL(value)); - case T_STRING: return qpid::types::Variant(StringValuePtr(value)); - case T_FIXNUM: return qpid::types::Variant((int64_t) FIX2LONG(value)); - case T_BIGNUM: return qpid::types::Variant((int64_t) NUM2LL(value)); - case T_TRUE: return qpid::types::Variant(true); - case T_FALSE: return qpid::types::Variant(false); - case T_HASH: { - qpid::types::Variant::Map map; - RbToMap(value, &map); - return qpid::types::Variant(map); - } - case T_ARRAY: { - qpid::types::Variant::List list; - RbToList(value, &list); - return qpid::types::Variant(list); - } - default: return qpid::types::Variant(); - } - } - - VALUE VariantToRb(const qpid::types::Variant* v) { - VALUE result = Qnil; - try { - switch (v->getType()) { - case qpid::types::VAR_VOID: { - result = Qnil; - break; - } - case qpid::types::VAR_BOOL : { - result = v->asBool() ? Qtrue : Qfalse; - break; - } - case qpid::types::VAR_UINT8 : - case qpid::types::VAR_UINT16 : - case qpid::types::VAR_UINT32 : { - result = UINT2NUM(v->asUint32()); - break; - } - case qpid::types::VAR_UINT64 : { - result = ULL2NUM(v->asUint64()); - break; - } - case qpid::types::VAR_INT8 : - case qpid::types::VAR_INT16 : - case qpid::types::VAR_INT32 : { - result = INT2NUM(v->asInt32()); - break; - } - case qpid::types::VAR_INT64 : { - result = LL2NUM(v->asInt64()); - break; - } - case qpid::types::VAR_FLOAT : { - result = rb_float_new((double) v->asFloat()); - break; - } - case qpid::types::VAR_DOUBLE : { - result = rb_float_new(v->asDouble()); - break; - } - case qpid::types::VAR_STRING : { - const std::string val(v->asString()); - result = rb_str_new(val.c_str(), val.size()); - break; - } - case qpid::types::VAR_MAP : { - result = MapToRb(&(v->asMap())); - break; - } - case qpid::types::VAR_LIST : { - result = ListToRb(&(v->asList())); - break; - } - case qpid::types::VAR_UUID : { - } - } - } catch (qpid::types::Exception& ex) { - static VALUE error = rb_define_class("Error", rb_eStandardError); - rb_raise(error, ex.what()); - } - - return result; - } - - VALUE MapToRb(const qpid::types::Variant::Map* map) { - VALUE result = rb_hash_new(); - qpid::types::Variant::Map::const_iterator iter; - for (iter = map->begin(); iter != map->end(); iter++) { - const std::string key(iter->first); - VALUE rbval = VariantToRb(&(iter->second)); - rb_hash_aset(result, rb_str_new(key.c_str(), key.size()), rbval); - } - return result; - } - - VALUE ListToRb(const qpid::types::Variant::List* list) { - VALUE result = rb_ary_new2(list->size()); - qpid::types::Variant::List::const_iterator iter; - for (iter = list->begin(); iter != list->end(); iter++) { - VALUE rbval = VariantToRb(&(*iter)); - rb_ary_push(result, rbval); - } - return result; - } - - VALUE HashIter(VALUE data_ary, VALUE context) { - VALUE key = rb_ary_entry(data_ary, 0); - VALUE val = rb_ary_entry(data_ary, 1); - qpid::types::Variant::Map* map((qpid::types::Variant::Map*) context); - (*map)[std::string(StringValuePtr(key))] = RbToVariant(val); - return data_ary; - } - - VALUE AryIter(VALUE data, VALUE context) { - qpid::types::Variant::List* list((qpid::types::Variant::List*) context); - list->push_back(RbToVariant(data)); - return data; - } - - void RbToMap(VALUE hash, qpid::types::Variant::Map* map) { - map->clear(); - rb_iterate(rb_each, hash, (VALUE(*)(ANYARGS))HashIter, (VALUE) map); - } - - void RbToList(VALUE ary, qpid::types::Variant::List* list) { - list->clear(); - rb_iterate(rb_each, ary, (VALUE(*)(ANYARGS))AryIter, (VALUE) list); - } -%} - -%typemap (in) void * -{ - $1 = (void *) $input; -} - -%typemap (out) void * -{ - $result = (VALUE) $1; -} - -%typemap (in) uint8_t -{ - $1 = NUM2UINT ($input); -} - -%typemap (out) uint8_t -{ - $result = UINT2NUM((uint8_t) $1); -} - -%typemap (in) int8_t -{ - $1 = NUM2INT ($input); -} - -%typemap (out) int8_t -{ - $result = INT2NUM((int8_t) $1); -} - -%typemap (in) uint16_t -{ - $1 = NUM2UINT ($input); -} - -%typemap (out) uint16_t -{ - $result = UINT2NUM((uint16_t) $1); -} - -%typemap (in) uint32_t -{ - if (TYPE($input) == T_BIGNUM) - $1 = NUM2UINT($input); - else - $1 = FIX2UINT($input); -} - -%typemap (out) uint32_t -{ - $result = UINT2NUM((uint32_t) $1); -} - -%typemap (in) int32_t -{ - if (TYPE($input) == T_BIGNUM) - $1 = NUM2INT($input); - else - $1 = FIX2INT($input); -} - -%typemap (out) int32_t -{ - $result = INT2NUM((int32_t) $1); -} - -%typemap (typecheck, precedence=SWIG_TYPECHECK_INTEGER) uint32_t { - $1 = FIXNUM_P($input); -} - -%typemap (in) uint64_t -{ - if (TYPE($input) == T_BIGNUM) - $1 = NUM2ULL($input); - else - $1 = (uint64_t) FIX2ULONG($input); -} - -%typemap (out) uint64_t -{ - $result = ULL2NUM((uint64_t) $1); -} - -%typemap (in) int64_t -{ - if (TYPE($input) == T_BIGNUM) - $1 = NUM2LL($input); - else - $1 = (int64_t) FIX2LONG($input); -} - -%typemap (out) int64_t -{ - $result = LL2NUM((int64_t) $1); -} - -/* - * Variant types: C++ --> Ruby - */ -%typemap(out) qpid::types::Variant::Map { - $result = MapToRb(&$1); -} - -%typemap(out) qpid::types::Variant::Map& { - $result = MapToRb($1); -} - -%typemap(out) qpid::types::Variant::List { - $result = ListToRb(&$1); -} - -%typemap(out) qpid::types::Variant::List& { - $result = ListToRb($1); -} - -%typemap(out) qpid::types::Variant& { - $result = VariantToRb($1); -} - - -/* - * Variant types: Ruby --> C++ - */ -%typemap(in) qpid::types::Variant& { - $1 = new qpid::types::Variant(RbToVariant($input)); -} - -%typemap(in) qpid::types::Variant::Map& { - $1 = new qpid::types::Variant::Map(); - RbToMap($input, $1); -} - -%typemap(in) qpid::types::Variant::List& { - $1 = new qpid::types::Variant::List(); - RbToList($input, $1); -} - -%typemap(in) const qpid::types::Variant::Map const & { - $1 = new qpid::types::Variant::Map(); - RbToMap($input, $1); -} - -%typemap(in) const qpid::types::Variant::List const & { - $1 = new qpid::types::Variant::List(); - RbToList($input, $1); -} - -%typemap(freearg) qpid::types::Variant& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::Map& { - delete $1; -} - -%typemap(freearg) qpid::types::Variant::List& { - delete $1; -} - - -/* - * Variant types: typecheck maps - */ -%typemap(typecheck) qpid::types::Variant::Map& { - $1 = (TYPE($input) == T_HASH) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant::List& { - $1 = (TYPE($input) == T_ARRAY) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant& { - $1 = (TYPE($input) == T_FLOAT || - TYPE($input) == T_STRING || - TYPE($input) == T_FIXNUM || - TYPE($input) == T_BIGNUM || - TYPE($input) == T_TRUE || - TYPE($input) == T_FALSE) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant::Map const & { - $1 = (TYPE($input) == T_HASH) ? 1 : 0; -} - -%typemap(typecheck) qpid::types::Variant::List const & { - $1 = (TYPE($input) == T_ARRAY) ? 1 : 0; -} - -%typemap(typecheck) const qpid::types::Variant const & { - $1 = (TYPE($input) == T_FLOAT || - TYPE($input) == T_STRING || - TYPE($input) == T_FIXNUM || - TYPE($input) == T_BIGNUM || - TYPE($input) == T_TRUE || - TYPE($input) == T_FALSE) ? 1 : 0; -} - -%typemap(typecheck) bool { - $1 = (TYPE($input) == T_TRUE || - TYPE($input) == T_FALSE) ? 1 : 0; -} - - - -%typemap (typecheck, precedence=SWIG_TYPECHECK_INTEGER) uint64_t { - $1 = FIXNUM_P($input); -} - -- cgit v1.2.1